diff --git a/UPGRADING.md b/UPGRADING.md index ec3723717..01f1a67dd 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -7,7 +7,7 @@ - [BC] The only optional boolean parameter of `TKeyedArray::getGenericArrayType` was removed, and was replaced with a string parameter with a different meaning. -- [BC] The `TDependentListKey` type was removed, replacing it with an optional property of the `TIntRange` type. +- [BC] The `TDependentListKey` type was removed and replaced with an optional property of the `TIntRange` type. # Upgrading from Psalm 4 to Psalm 5 ## Changed diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php index 598f0a305..4c0dd4ee1 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php @@ -106,14 +106,15 @@ class ForAnalyzer if (count($stmt->init) === 1 && count($stmt->cond) === 1 && $cond instanceof PhpParser\Node\Expr\BinaryOp - && $cond->right instanceof PhpParser\Node\Scalar\LNumber + && ($cond_value = $statements_analyzer->node_data->getType($cond->right)) + && ($cond_value->isSingleIntLiteral() || $cond_value->isSingleStringLiteral()) && $cond->left instanceof PhpParser\Node\Expr\Variable && is_string($cond->left->name) && isset($init_var_types[$cond->left->name]) && $init_var_types[$cond->left->name]->isSingleIntLiteral() ) { - $init_value = $init_var_types[$cond->left->name]->getSingleIntLiteral()->value; - $cond_value = $cond->right->value; + $init_value = $init_var_types[$cond->left->name]->getSingleLiteral()->value; + $cond_value = $cond_value->getSingleLiteral()->value; if ($cond instanceof PhpParser\Node\Expr\BinaryOp\Smaller && $init_value < $cond_value) { $always_enters_loop = true; diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php index e3a52f67e..a1fd17078 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php @@ -27,7 +27,8 @@ class WhileAnalyzer Context $context ): ?bool { $while_true = ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch && $stmt->cond->name->parts === ['true']) - || ($stmt->cond instanceof PhpParser\Node\Scalar\LNumber && $stmt->cond->value > 0); + || (($t = $statements_analyzer->node_data->getType($stmt->cond)) + && $t->isAlwaysTruthy()); $pre_context = null; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php index 2cae6ff6a..0a7af6d59 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php @@ -334,7 +334,16 @@ class IncludeAnalyzer if ($stmt->getArgs()[1]->value instanceof PhpParser\Node\Scalar\LNumber) { $dir_level = $stmt->getArgs()[1]->value->value; } else { - return null; + if ($statements_analyzer) { + $t = $statements_analyzer->node_data->getType($stmt->getArgs()[1]->value); + if ($t && $t->isSingleIntLiteral()) { + $dir_level = $t->getSingleIntLiteral()->value; + } else { + return null; + } + } else { + return null; + } } } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php index 56b478edf..f4a668905 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php @@ -2,7 +2,6 @@ namespace Psalm\Internal\Provider\ReturnTypeProvider; -use PhpParser; use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent; use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface; @@ -54,15 +53,21 @@ class ArrayRandReturnTypeProvider implements FunctionReturnTypeProviderInterface $key_type = $first_arg_array->getGenericKeyType(); } - if (!$second_arg - || ($second_arg instanceof PhpParser\Node\Scalar\LNumber && $second_arg->value === 1) + if (!$second_arg) { + return $key_type; + } + + $second_arg_type = $statements_source->node_data->getType($second_arg); + if ($second_arg_type + && $second_arg_type->isSingleIntLiteral() + && $second_arg_type->getSingleIntLiteral()->value === 1 ) { return $key_type; } $arr_type = Type::getList($key_type); - if ($second_arg instanceof PhpParser\Node\Scalar\LNumber) { + if ($second_arg_type && $second_arg_type->isSingleIntLiteral()) { return $arr_type; } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php index 15512b638..f1d3363fd 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php @@ -47,8 +47,9 @@ class ExplodeReturnTypeProvider implements FunctionReturnTypeProviderInterface $can_return_empty = isset($call_args[2]) && ( - !$call_args[2]->value instanceof PhpParser\Node\Scalar\LNumber - || $call_args[2]->value->value < 0 + !($third_arg_type = $statements_source->node_data->getType($call_args[2]->value)) + || !$third_arg_type->isSingleIntLiteral() + || $third_arg_type->getSingleIntLiteral()->value < 0 ); if ($call_args[0]->value instanceof PhpParser\Node\Scalar\String_) {