diff --git a/src/Parser/NodeTokensVisitor.php b/src/Parser/NodeTokensVisitor.php index efa668aa31..9e9e739d55 100644 --- a/src/Parser/NodeTokensVisitor.php +++ b/src/Parser/NodeTokensVisitor.php @@ -36,7 +36,7 @@ public function enterNode(Node $node) [$immediatePredecessor, $immediateSuccessor] = $this->getImmediates($parent, $myStart, $myEnd); if ($immediatePredecessor !== null) { $tokensBefore = []; - for ($i = $immediatePredecessor->getAttribute('endTokenPos') + 1; $i < $myStart; $i++) { + for ($i = $immediatePredecessor; $i < $myStart; $i++) { $tokensBefore[] = $this->tokens[$i]; } $node->setAttribute('tokensBefore', $tokensBefore); @@ -44,7 +44,7 @@ public function enterNode(Node $node) if ($immediateSuccessor !== null) { $tokensAfter = []; - for ($i = $myEnd + 1; $i < $immediateSuccessor->getAttribute('startTokenPos'); $i++) { + for ($i = $myEnd + 1; $i <= $immediateSuccessor; $i++) { $tokensAfter[] = $this->tokens[$i]; } $node->setAttribute('tokensAfter', $tokensAfter); @@ -58,7 +58,7 @@ public function enterNode(Node $node) * @param Node $parent * @param int $myStart * @param int $myEnd - * @return array{Node|null, Node|null} + * @return array{int|null, int|null} */ private function getImmediates(Node $parent, int $myStart, int $myEnd): array { @@ -71,17 +71,21 @@ private function getImmediates(Node $parent, int $myStart, int $myEnd): array $parentChild = $parentChildList->getNode(); $childEnd = $parentChild->getAttribute('endTokenPos'); if ($childEnd < $myStart) { - $immediatePredecessor = $parentChild; + $immediatePredecessor = $childEnd + 1; $parentChildList = $parentChildList->getNext(); continue; } $childStart = $parentChild->getAttribute('startTokenPos'); if ($childStart > $myEnd) { - $immediateSuccessor = $parentChild; + $immediateSuccessor = $childStart - 1; break; } + if ($childStart + 1 < $myStart && $childEnd > $myEnd) { + return [$childStart + 1, $childEnd]; + } + $parentChildList = $parentChildList->getNext(); } diff --git a/tests/PHPStan/Rules/Ternary/RequireParenthesesForNestedTernaryRuleTest.php b/tests/PHPStan/Rules/Ternary/RequireParenthesesForNestedTernaryRuleTest.php index 3a6d76f927..1cfda5b3cc 100644 --- a/tests/PHPStan/Rules/Ternary/RequireParenthesesForNestedTernaryRuleTest.php +++ b/tests/PHPStan/Rules/Ternary/RequireParenthesesForNestedTernaryRuleTest.php @@ -48,4 +48,10 @@ public function testReportOnPhp80(): void ]); } + public function testBug(): void + { + $this->phpVersion = new PhpVersion(80000); + $this->analyse([__DIR__ . '/data/require-parentheses-bug.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Ternary/data/require-parentheses-bug.php b/tests/PHPStan/Rules/Ternary/data/require-parentheses-bug.php new file mode 100644 index 0000000000..e060b6a89d --- /dev/null +++ b/tests/PHPStan/Rules/Ternary/data/require-parentheses-bug.php @@ -0,0 +1,14 @@ +hasAddress() ? $premise->getAddress() : null; + + return $address !== null && $address->getCity() !== null && $address->getStreet() !== null + ? sprintf('%s, %s, %s', $premise->getName(), $address->getStreet(), $address->getCity()) + : ($address !== null && $address->getCity() !== null + ? sprintf('%s, %s', $premise->getName(), $address->getCity()) + : $premise->getName()); +}