Skip to content

Commit

Permalink
[Traverser] Remove next attribute in BetterNodeFinder (#3887)
Browse files Browse the repository at this point in the history
* [Traverser] Remove next attribute in BetterNodeFinder

* Fix set key

* fix cs

* check current node

* Revert check current node

This reverts commit 93e1c8f.

* cover a FileWithoutNamespace and Namespace_

* check current early

* beforeTraverse() and afterTraverse() is always Stmt inside

* beforeTraverse() and afterTraverse() is always Stmt inside

* remove unused use

* clean up namespace check

* check

* docblock fix

* check

* try with resolve neighbor stmt just removed check

* nullable key

* Fix key null

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* only verify next node

---------

Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
samsonasik and actions-user committed May 19, 2023
1 parent 9fff8d3 commit aef093e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,52 @@
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;

use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\NodeVisitorAbstract;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface;

final class StmtKeyNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface
{
/**
* @param Node[] $nodes
* @return Node[]
*/
public function beforeTraverse(array $nodes): array
{
// count = 1 is essential here as FileWithoutNamespace can merge with other Stmt
if (count($nodes) === 1) {
$currentNode = current($nodes);
if ($currentNode instanceof FileWithoutNamespace) {
foreach ($currentNode->stmts as $key => $stmt) {
$stmt->setAttribute(AttributeKey::STMT_KEY, $key);
}
}

return $nodes;
}

foreach ($nodes as $key => $node) {
$node->setAttribute(AttributeKey::STMT_KEY, $key);
}

return $nodes;
}

/**
* @param Node[] $nodes
* @return Node[]
*/
public function afterTraverse(array $nodes): array
{
foreach ($nodes as $key => $node) {
if ($node instanceof Stmt) {
$node->setAttribute(AttributeKey::STMT_KEY, $key);
if (! $node instanceof Namespace_) {
return $nodes;
}

$node->setAttribute(AttributeKey::STMT_KEY, $key);
}

return $nodes;
Expand All @@ -34,6 +62,11 @@ public function enterNode(Node $node): ?Node
return null;
}

// covered on beforeTraverse() as top level node handling
if ($node instanceof FileWithoutNamespace) {
return null;
}

if ($node->stmts === null) {
return null;
}
Expand Down
24 changes: 20 additions & 4 deletions src/PhpParser/Node/BetterNodeFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,23 @@ public function resolveCurrentStatement(Node $node): ?Stmt
return null;
}

private function resolveNeighborNextStmt(StmtsAwareInterface $stmtsAware, Stmt $stmt, ?int $key): ?Node
{
if ($key === null) {
$key = 0;
}

if (!isset($stmtsAware->stmts[$key - 1])) {
return $stmtsAware->stmts[$key + 1] ?? null;
}

if ($stmtsAware->stmts[$key - 1]->getStartTokenPos() !== $stmt->getStartTokenPos()) {
return $stmtsAware->stmts[$key + 1] ?? null;
}

return $stmt;
}

/**
* Only search in next Node/Stmt
*
Expand All @@ -549,9 +566,8 @@ private function findFirstInlinedNext(Node $node, callable $filter, array $newSt
return null;
}

// todo: use +1 key once all next node attribute reference and NodeConnectingVisitor removed
// left with add SlimNodeConnectingVisitor for only lookup parent
$nextNode = $node->getAttribute(AttributeKey::NEXT_NODE);
$currentStmtKey = $node->getAttribute(AttributeKey::STMT_KEY);
$nextNode = $this->resolveNeighborNextStmt($parentNode, $node, $currentStmtKey);
} else {
$nextNode = $this->resolveNextNodeFromOtherNode($node);
}
Expand Down Expand Up @@ -734,7 +750,7 @@ private function findFirstInlinedPrevious(Node $node, callable $filter, array $n
return $this->findFirstInTopLevelStmtsAware($parentNode, $filter);
}

$previousNode = $parentNode->stmts[$currentStmtKey - 1];
$previousNode = $parentNode->stmts[$currentStmtKey - 1] ?? null;
} else {
$previousNode = $this->resolvePreviousNodeFromOtherNode($node);
}
Expand Down

0 comments on commit aef093e

Please sign in to comment.