mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 12:55:26 +01:00
Merge pull request #8828 from orklah/generator
fix missing break handling in loop
This commit is contained in:
commit
df4d3692ab
@ -23,6 +23,7 @@ class ScopeAnalyzer
|
||||
public const ACTION_BREAK = 'BREAK';
|
||||
public const ACTION_CONTINUE = 'CONTINUE';
|
||||
public const ACTION_LEAVE_SWITCH = 'LEAVE_SWITCH';
|
||||
public const ACTION_LEAVE_LOOP = 'LEAVE_LOOP';
|
||||
public const ACTION_NONE = 'NONE';
|
||||
public const ACTION_RETURN = 'RETURN';
|
||||
|
||||
@ -107,6 +108,10 @@ class ScopeAnalyzer
|
||||
return [...$control_actions, ...[self::ACTION_LEAVE_SWITCH]];
|
||||
}
|
||||
|
||||
if ($break_types[count($break_types) - $count] === 'loop') {
|
||||
return [...$control_actions, ...[self::ACTION_LEAVE_LOOP]];
|
||||
}
|
||||
|
||||
return array_values($control_actions);
|
||||
}
|
||||
|
||||
@ -263,6 +268,7 @@ class ScopeAnalyzer
|
||||
&& $nodes
|
||||
&& ($stmt_expr_type = $nodes->getType($stmt->cond))
|
||||
&& $stmt_expr_type->isAlwaysTruthy()
|
||||
&& !in_array(self::ACTION_LEAVE_LOOP, $control_actions, true)
|
||||
) {
|
||||
//infinite while loop that only return don't have an exit path
|
||||
$have_exit_path = (bool)array_diff(
|
||||
@ -277,6 +283,7 @@ class ScopeAnalyzer
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\For_
|
||||
&& $nodes
|
||||
&& !in_array(self::ACTION_LEAVE_LOOP, $control_actions, true)
|
||||
) {
|
||||
$is_infinite_loop = true;
|
||||
if ($stmt->cond) {
|
||||
@ -300,6 +307,11 @@ class ScopeAnalyzer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$control_actions = array_filter(
|
||||
$control_actions,
|
||||
static fn(string $action): bool => $action !== self::ACTION_LEAVE_LOOP
|
||||
);
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\TryCatch) {
|
||||
|
@ -676,6 +676,21 @@ class WhileTest extends TestCase
|
||||
}
|
||||
}'
|
||||
],
|
||||
'breakInWhileTrueIsNotInfiniteLoop' => [
|
||||
'code' => '<?php
|
||||
/** @return Generator<array-key, mixed> */
|
||||
function f()
|
||||
{
|
||||
if (rand(0,1)) {
|
||||
throw new Exception;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
yield 1;
|
||||
break;
|
||||
}
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user