mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 22:01:48 +01:00
Merge pull request #8360 from bitwise-operators/8307-operand-class-constants
Add BitwiseNot and BooleanNot operators to SimpleTypeInferer
This commit is contained in:
commit
ffc8c8080d
@ -203,6 +203,63 @@ class SimpleTypeInferer
|
||||
}
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\BitwiseNot) {
|
||||
$stmt_expr_type = self::infer(
|
||||
$codebase,
|
||||
$nodes,
|
||||
$stmt->expr,
|
||||
$aliases,
|
||||
$file_source,
|
||||
$existing_class_constants,
|
||||
$fq_classlike_name
|
||||
);
|
||||
|
||||
if ($stmt_expr_type === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$invalidTypes = clone $stmt_expr_type;
|
||||
$invalidTypes->removeType('string');
|
||||
$invalidTypes->removeType('int');
|
||||
$invalidTypes->removeType('float');
|
||||
|
||||
if (!$invalidTypes->isUnionEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$types = [];
|
||||
if ($stmt_expr_type->hasString()) {
|
||||
$types[] = Type::getString();
|
||||
}
|
||||
if ($stmt_expr_type->hasInt() || $stmt_expr_type->hasFloat()) {
|
||||
$types[] = Type::getInt();
|
||||
}
|
||||
|
||||
return $types ? Type::combineUnionTypeArray($types, null) : null;
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\BooleanNot) {
|
||||
$stmt_expr_type = self::infer(
|
||||
$codebase,
|
||||
$nodes,
|
||||
$stmt->expr,
|
||||
$aliases,
|
||||
$file_source,
|
||||
$existing_class_constants,
|
||||
$fq_classlike_name
|
||||
);
|
||||
|
||||
if ($stmt_expr_type === null) {
|
||||
return null;
|
||||
} elseif ($stmt_expr_type->isAlwaysFalsy()) {
|
||||
return Type::getTrue();
|
||||
} elseif ($stmt_expr_type->isAlwaysTruthy()) {
|
||||
return Type::getFalse();
|
||||
} else {
|
||||
return Type::getBool();
|
||||
}
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\ConstFetch) {
|
||||
$name = strtolower($stmt->name->parts[0]);
|
||||
if ($name === 'false') {
|
||||
|
@ -998,6 +998,60 @@ class ConstantTest extends TestCase
|
||||
'$c' => 'int',
|
||||
]
|
||||
],
|
||||
'bitwiseAndClassConstant' => [
|
||||
'code' => '<?php
|
||||
class X {
|
||||
public const A = 1;
|
||||
public const B = 2;
|
||||
public const C = self::A & self::B;
|
||||
}
|
||||
|
||||
$c = X::C;',
|
||||
'assertions' => [
|
||||
'$c' => 'int',
|
||||
]
|
||||
],
|
||||
'bitwiseXorClassConstant' => [
|
||||
'code' => '<?php
|
||||
class X {
|
||||
public const A = 1;
|
||||
public const B = 2;
|
||||
public const C = self::A ^ self::B;
|
||||
}
|
||||
|
||||
$c = X::C;',
|
||||
'assertions' => [
|
||||
'$c' => 'int',
|
||||
]
|
||||
],
|
||||
'bitwiseNotClassConstant' => [
|
||||
'code' => '<?php
|
||||
class X {
|
||||
public const A = ~0;
|
||||
public const B = ~"aa";
|
||||
}
|
||||
|
||||
$a = X::A;
|
||||
$b = X::B;',
|
||||
'assertions' => [
|
||||
'$a' => 'int',
|
||||
'$b' => 'string',
|
||||
]
|
||||
],
|
||||
'booleanNotClassConstant' => [
|
||||
'code' => '<?php
|
||||
class X {
|
||||
public const A = !true;
|
||||
public const B = !false;
|
||||
}
|
||||
|
||||
$a = X::A;
|
||||
$b = X::B;',
|
||||
'assertions' => [
|
||||
'$a' => 'false',
|
||||
'$b' => 'true',
|
||||
]
|
||||
],
|
||||
'protectedClassConstantAccessibilitySameNameInChild' => [
|
||||
'code' => '<?php
|
||||
class A {
|
||||
|
Loading…
x
Reference in New Issue
Block a user