1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Make Psalm understand infinite while loop in control actions

This commit is contained in:
orklah 2021-09-02 21:47:10 +02:00
parent eb973ab2e1
commit e99c1951ae
2 changed files with 56 additions and 0 deletions

View File

@ -345,6 +345,22 @@ class ScopeAnalyzer
return $action !== self::ACTION_NONE;
}
);
if ($stmt instanceof PhpParser\Node\Stmt\While_
&& $nodes
&& ($stmt_expr_type = $nodes->getType($stmt->cond))
&& $stmt_expr_type->isTrue()
) {
//infinite while loop that only return don't have an exit path
$have_exit_path = (bool)array_diff(
$control_actions,
[self::ACTION_END, self::ACTION_RETURN]
);
if (!$have_exit_path) {
return array_values(array_unique($control_actions));
}
}
}
if ($stmt instanceof PhpParser\Node\Stmt\TryCatch) {

View File

@ -708,6 +708,46 @@ class WhileTest extends \Psalm\Tests\TestCase
if ($a->foo !== null) {}
}'
],
'whileTrueDontHaveExitPathForReturn' => [
'<?php
function getResultWithRetry(): string
{
while (true) {
return "";
}
}'
],
'ComplexWhileTrueDontHaveExitPathForReturn' => [
'<?php
class Test {
private int $retryAttempts = 10;
private function getResult(): string
{
// return tring or throw exception whatever
throw new Exception();
}
private function getResultWithRetry(): string
{
$attempt = 1;
while (true) {
try {
return $this->getResult();
} catch (Throwable $exception) {
if ($attempt >= $this->retryAttempts) {
throw $exception;
}
$attempt++;
continue;
}
}
}
}'
],
];
}