From 2490230f1fd728becffc95afb339190f3169ea37 Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 4 Dec 2022 13:37:29 +0100 Subject: [PATCH] fix missing break handling in loop --- src/Psalm/Internal/Analyzer/ScopeAnalyzer.php | 12 ++++++++++++ tests/Loop/WhileTest.php | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php b/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php index 6acfefb98f3..860cbc38d2b 100644 --- a/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php @@ -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 @@ public static function getControlActions( 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 @@ public static function getControlActions( && $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 @@ public static function getControlActions( 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 @@ public static function getControlActions( } } } + + $control_actions = array_filter( + $control_actions, + static fn(string $action): bool => $action !== self::ACTION_LEAVE_LOOP + ); } if ($stmt instanceof PhpParser\Node\Stmt\TryCatch) { diff --git a/tests/Loop/WhileTest.php b/tests/Loop/WhileTest.php index 31bdc6045c5..3fa0380f8e2 100644 --- a/tests/Loop/WhileTest.php +++ b/tests/Loop/WhileTest.php @@ -676,6 +676,21 @@ function breakUpPathIntoParts(): void { } }' ], + 'breakInWhileTrueIsNotInfiniteLoop' => [ + 'code' => ' */ + function f() + { + if (rand(0,1)) { + throw new Exception; + } + + while (true) { + yield 1; + break; + } + }' + ], ]; }