1
0
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:
orklah 2022-08-04 20:30:52 +02:00 committed by GitHub
commit ffc8c8080d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 111 additions and 0 deletions

View File

@ -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') {

View File

@ -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 {