1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

add test and allow checking in already inferred types instead of just relying on statements from PHPParser for assertions

This commit is contained in:
orklah 2021-09-12 11:33:23 +02:00
parent ae0586b0e6
commit f789ab0655
2 changed files with 44 additions and 4 deletions

View File

@ -1562,13 +1562,20 @@ class AssertionFinder
* @return false|int * @return false|int
*/ */
protected static function hasSuperiorNumberCheck( protected static function hasSuperiorNumberCheck(
FileSource $source,
PhpParser\Node\Expr\BinaryOp $conditional, PhpParser\Node\Expr\BinaryOp $conditional,
?int &$literal_value_comparison, ?int &$literal_value_comparison,
bool &$isset_assert bool &$isset_assert
) { ) {
$right_assignment = false; $right_assignment = false;
$value_right = null; $value_right = null;
if ($conditional->right instanceof LNumber) { if ($source instanceof StatementsAnalyzer
&& ($type = $source->node_data->getType($conditional->right))
&& $type->isSingleIntLiteral()
) {
$right_assignment = true;
$value_right = $type->getSingleIntLiteral()->value;
} elseif ($conditional->right instanceof LNumber) {
$right_assignment = true; $right_assignment = true;
$value_right = $conditional->right->value; $value_right = $conditional->right->value;
} elseif ($conditional->right instanceof UnaryMinus && $conditional->right->expr instanceof LNumber) { } elseif ($conditional->right instanceof UnaryMinus && $conditional->right->expr instanceof LNumber) {
@ -1589,7 +1596,13 @@ class AssertionFinder
$left_assignment = false; $left_assignment = false;
$value_left = null; $value_left = null;
if ($conditional->left instanceof LNumber) { if ($source instanceof StatementsAnalyzer
&& ($type = $source->node_data->getType($conditional->left))
&& $type->isSingleIntLiteral()
) {
$left_assignment = true;
$value_left = $type->getSingleIntLiteral()->value;
} elseif ($conditional->left instanceof LNumber) {
$left_assignment = true; $left_assignment = true;
$value_left = $conditional->left->value; $value_left = $conditional->left->value;
} elseif ($conditional->left instanceof UnaryMinus && $conditional->left->expr instanceof LNumber) { } elseif ($conditional->left instanceof UnaryMinus && $conditional->left->expr instanceof LNumber) {
@ -1616,13 +1629,20 @@ class AssertionFinder
* @return false|int * @return false|int
*/ */
protected static function hasInferiorNumberCheck( protected static function hasInferiorNumberCheck(
FileSource $source,
PhpParser\Node\Expr\BinaryOp $conditional, PhpParser\Node\Expr\BinaryOp $conditional,
?int &$literal_value_comparison, ?int &$literal_value_comparison,
bool &$isset_assert bool &$isset_assert
) { ) {
$right_assignment = false; $right_assignment = false;
$value_right = null; $value_right = null;
if ($conditional->right instanceof LNumber) { if ($source instanceof StatementsAnalyzer
&& ($type = $source->node_data->getType($conditional->right))
&& $type->isSingleIntLiteral()
) {
$right_assignment = true;
$value_right = $type->getSingleIntLiteral()->value;
} elseif ($conditional->right instanceof LNumber) {
$right_assignment = true; $right_assignment = true;
$value_right = $conditional->right->value; $value_right = $conditional->right->value;
} elseif ($conditional->right instanceof UnaryMinus && $conditional->right->expr instanceof LNumber) { } elseif ($conditional->right instanceof UnaryMinus && $conditional->right->expr instanceof LNumber) {
@ -1642,7 +1662,13 @@ class AssertionFinder
$left_assignment = false; $left_assignment = false;
$value_left = null; $value_left = null;
if ($conditional->left instanceof LNumber) { if ($source instanceof StatementsAnalyzer
&& ($type = $source->node_data->getType($conditional->left))
&& $type->isSingleIntLiteral()
) {
$left_assignment = true;
$value_left = $type->getSingleIntLiteral()->value;
} elseif ($conditional->left instanceof LNumber) {
$left_assignment = true; $left_assignment = true;
$value_left = $conditional->left->value; $value_left = $conditional->left->value;
} elseif ($conditional->left instanceof UnaryMinus && $conditional->left->expr instanceof LNumber) { } elseif ($conditional->left instanceof UnaryMinus && $conditional->left->expr instanceof LNumber) {
@ -3676,6 +3702,7 @@ class AssertionFinder
$isset_assert = false; $isset_assert = false;
$superior_value_comparison = null; $superior_value_comparison = null;
$superior_value_position = self::hasSuperiorNumberCheck( $superior_value_position = self::hasSuperiorNumberCheck(
$source,
$conditional, $conditional,
$superior_value_comparison, $superior_value_comparison,
$isset_assert $isset_assert
@ -3791,6 +3818,7 @@ class AssertionFinder
$isset_assert = false; $isset_assert = false;
$inferior_value_comparison = null; $inferior_value_comparison = null;
$inferior_value_position = self::hasInferiorNumberCheck( $inferior_value_position = self::hasInferiorNumberCheck(
$source,
$conditional, $conditional,
$inferior_value_comparison, $inferior_value_comparison,
$isset_assert $isset_assert

View File

@ -58,6 +58,18 @@ class IntRangeTest extends TestCase
'$c===' => 'int<-499, -61>', '$c===' => 'int<-499, -61>',
] ]
], ],
'complexAssertions' => [
'<?php
function getInt(): int{return 0;}
$a = getInt();
assert($a >= 495 + 5);
$b = 5000;
assert($a < $b);
',
'assertions' => [
'$a===' => 'int<500, 4999>',
]
],
'negatedAssertions' => [ 'negatedAssertions' => [
'<?php '<?php
function getInt(): int{return 0;} function getInt(): int{return 0;}