From 20fce3b76e3e6bbe510b79e11387831854b6cc3d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 21 May 2023 06:33:48 +0700 Subject: [PATCH] [Parser] Allow resolve next/prev stmt inside ClassLike or Declare_ on BetterNodeFinder (#3905) * [Parser] Allow resolve next/prev stmt inside ClassLike or Declare_ * add var * Fix --- src/PhpParser/Node/BetterNodeFinder.php | 43 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/PhpParser/Node/BetterNodeFinder.php b/src/PhpParser/Node/BetterNodeFinder.php index 25e3ae4fcf0..1f0c5cd4af3 100644 --- a/src/PhpParser/Node/BetterNodeFinder.php +++ b/src/PhpParser/Node/BetterNodeFinder.php @@ -17,6 +17,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Declare_; use PhpParser\Node\Stmt\Do_; use PhpParser\Node\Stmt\ElseIf_; use PhpParser\Node\Stmt\For_; @@ -534,8 +535,16 @@ public function resolveCurrentStatement(Node $node): ?Stmt return null; } - private function resolveNeighborNextStmt(StmtsAwareInterface $stmtsAware, Stmt $stmt, int $key): ?Node + private function isAllowedParentNode(?Node $node): bool { + return $node instanceof StmtsAwareInterface || $node instanceof ClassLike || $node instanceof Declare_; + } + + private function resolveNeighborNextStmt( + StmtsAwareInterface|ClassLike|Declare_ $stmtsAware, + Stmt $stmt, + int $key + ): ?Node { if (! isset($stmtsAware->stmts[$key - 1])) { return $stmtsAware->stmts[$key + 1] ?? null; } @@ -567,11 +576,12 @@ private function findFirstInlinedNext(Node $node, callable $filter, array $newSt if (! $parentNode instanceof Node) { $nextNode = $this->resolveNextNodeFromFile($newStmts, $node); } elseif ($node instanceof Stmt) { - if (! $parentNode instanceof StmtsAwareInterface) { + if (! $this->isAllowedParentNode($parentNode)) { return null; } $currentStmtKey = $node->getAttribute(AttributeKey::STMT_KEY); + /** @var StmtsAwareInterface|ClassLike|Declare_ $parentNode */ $nextNode = $this->resolveNeighborNextStmt($parentNode, $node, $currentStmtKey); } else { $nextNode = $this->resolveNextNodeFromOtherNode($node); @@ -610,8 +620,10 @@ private function resolveNewStmts(?Node $parentNode): array /** * @param callable(Node $node): bool $filter */ - private function findFirstInTopLevelStmtsAware(StmtsAwareInterface $stmtsAware, callable $filter): ?Node - { + private function findFirstInTopLevelStmtsAware( + StmtsAwareInterface|ClassLike|Declare_ $stmtsAware, + callable $filter + ): ?Node { $nodes = []; if ($stmtsAware instanceof Foreach_) { @@ -721,18 +733,18 @@ private function resolvePreviousNodeFromOtherNode(Node $node): ?Node return null; } - $nodes = $this->find( - $currentStmt, - static fn (Node $subNode): bool => $subNode->getEndTokenPos() < $startTokenPos - ); + $nodes = $node instanceof Stmt + ? [] + : $this->find($currentStmt, static fn (Node $subNode): bool => $subNode->getEndTokenPos() < $startTokenPos); if ($nodes === []) { $parentNode = $currentStmt->getAttribute(AttributeKey::PARENT_NODE); - if (! $parentNode instanceof StmtsAwareInterface) { + if (! $this->isAllowedParentNode($parentNode)) { return null; } $currentStmtKey = $currentStmt->getAttribute(AttributeKey::STMT_KEY); + /** @var StmtsAwareInterface|ClassLike|Declare_ $parentNode */ return $parentNode->stmts[$currentStmtKey - 1] ?? null; } @@ -757,18 +769,18 @@ private function resolveNextNodeFromOtherNode(Node $node): ?Node return null; } - $nextNode = $this->findFirst( - $currentStmt, - static fn (Node $subNode): bool => $subNode->getStartTokenPos() > $endTokenPos - ); + $nextNode = $node instanceof Stmt + ? null + : $this->findFirst($currentStmt, static fn (Node $subNode): bool => $subNode->getStartTokenPos() > $endTokenPos); if (! $nextNode instanceof Node) { $parentNode = $currentStmt->getAttribute(AttributeKey::PARENT_NODE); - if (! $parentNode instanceof StmtsAwareInterface) { + if (! $this->isAllowedParentNode($parentNode)) { return null; } $currentStmtKey = $currentStmt->getAttribute(AttributeKey::STMT_KEY); + /** @var StmtsAwareInterface|ClassLike|Declare_ $parentNode */ return $this->resolveNeighborNextStmt($parentNode, $currentStmt, $currentStmtKey); } @@ -786,11 +798,12 @@ private function findFirstInlinedPrevious(Node $node, callable $filter, array $n if (! $parentNode instanceof Node) { $previousNode = $this->resolvePreviousNodeFromFile($newStmts, $node); } elseif ($node instanceof Stmt) { - if (! $parentNode instanceof StmtsAwareInterface) { + if (! $this->isAllowedParentNode($parentNode)) { return null; } $currentStmtKey = $node->getAttribute(AttributeKey::STMT_KEY); + /** @var StmtsAwareInterface|ClassLike|Declare_ $parentNode */ if (! isset($parentNode->stmts[$currentStmtKey - 1])) { return $this->findFirstInTopLevelStmtsAware($parentNode, $filter); }