diff --git a/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_if_else_with_trailing_comment.php.inc b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_if_else_with_trailing_comment.php.inc new file mode 100644 index 00000000000..f5c8bf0de45 --- /dev/null +++ b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_if_else_with_trailing_comment.php.inc @@ -0,0 +1,39 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_infinite_while.php.inc b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_infinite_while.php.inc new file mode 100644 index 00000000000..95030eb7cec --- /dev/null +++ b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_infinite_while.php.inc @@ -0,0 +1,53 @@ + +----- + diff --git a/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_trailing_comment.php.inc b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_trailing_comment.php.inc new file mode 100644 index 00000000000..1b262cce5b2 --- /dev/null +++ b/rules-tests/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector/Fixture/always_terminated_try_catch_with_trailing_comment.php.inc @@ -0,0 +1,43 @@ + +----- + diff --git a/src/NodeAnalyzer/TerminatedNodeAnalyzer.php b/src/NodeAnalyzer/TerminatedNodeAnalyzer.php index bb9752dfbac..0a1423c5f38 100644 --- a/src/NodeAnalyzer/TerminatedNodeAnalyzer.php +++ b/src/NodeAnalyzer/TerminatedNodeAnalyzer.php @@ -273,6 +273,12 @@ private function isTerminatedInLastStmtsIf(If_ $if): bool */ private function isTerminatedInLastStmts(array $stmts): bool { + // a trailing comment is parsed as a Nop, which executes nothing and so + // must not hide the terminating stmt in front of it + while ($stmts !== [] && end($stmts) instanceof Nop) { + array_pop($stmts); + } + if ($stmts === []) { return false; } @@ -280,6 +286,12 @@ private function isTerminatedInLastStmts(array $stmts): bool $lastKey = array_key_last($stmts); $lastNode = $stmts[$lastKey]; + // an infinite loop with no break terminates its block as surely as a + // return does, the same way isAlwaysTerminated() reads it one level up + if ($lastNode instanceof While_ || $lastNode instanceof Do_ || $lastNode instanceof For_) { + return $this->isTerminatedInfiniteLoop($lastNode); + } + if ($lastNode instanceof Expression) { return $lastNode->expr instanceof Exit_ || $lastNode->expr instanceof Throw_; }