diff --git a/src/PhpDocParser/NodeVisitor/CallableNodeVisitor.php b/src/PhpDocParser/NodeVisitor/CallableNodeVisitor.php index bcb70edeecd..11d64ba3a0b 100644 --- a/src/PhpDocParser/NodeVisitor/CallableNodeVisitor.php +++ b/src/PhpDocParser/NodeVisitor/CallableNodeVisitor.php @@ -9,22 +9,15 @@ use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Expression; use PhpParser\NodeVisitor; -use PhpParser\NodeVisitorAbstract; +use Rector\PhpParser\NodeVisitor\AbstractLeaveNode; -final class CallableNodeVisitor extends NodeVisitorAbstract +final class CallableNodeVisitor extends AbstractLeaveNode { /** * @var callable(Node): (int|Node|null|Node[]) */ private $callable; - private ?int $nodeIdToRemove = null; - - /** - * @var array - */ - private array $nodesToReturn = []; - /** * @param callable(Node $node): (int|Node|null|Node[]) $callable */ @@ -43,7 +36,7 @@ public function enterNode(Node $node): int|Node|null $newNode = $callable($node); if ($newNode === NodeVisitor::REMOVE_NODE) { - $this->nodeIdToRemove = spl_object_id($originalNode); + $this->toBeRemovedNodeId = spl_object_id($originalNode); return $originalNode; } @@ -60,21 +53,4 @@ public function enterNode(Node $node): int|Node|null return $newNode; } - - /** - * @return int|Node|Node[] - */ - public function leaveNode(Node $node): int|Node|array - { - if ($this->nodeIdToRemove !== null && $this->nodeIdToRemove === spl_object_id($node)) { - $this->nodeIdToRemove = null; - return NodeVisitor::REMOVE_NODE; - } - - if ($this->nodesToReturn === []) { - return $node; - } - - return $this->nodesToReturn[spl_object_id($node)] ?? $node; - } } diff --git a/src/PhpParser/NodeVisitor/AbstractLeaveNode.php b/src/PhpParser/NodeVisitor/AbstractLeaveNode.php new file mode 100644 index 00000000000..93b9dc2713a --- /dev/null +++ b/src/PhpParser/NodeVisitor/AbstractLeaveNode.php @@ -0,0 +1,45 @@ + + */ + protected array $nodesToReturn = []; + + /** + * Replacing nodes in leaveNode() method avoids infinite recursion + * see"infinite recursion" in https://github.com/nikic/PHP-Parser/blob/master/doc/component/Walking_the_AST.markdown + * + * @return NodeVisitor::REMOVE_NODE|Node|null|Node[] + */ + final public function leaveNode(Node $node): int|Node|null|array + { + // nothing to change here + if ($this->toBeRemovedNodeId === null && $this->nodesToReturn === []) { + return null; + } + + $objectId = spl_object_id($node); + if ($this->toBeRemovedNodeId === $objectId) { + $this->toBeRemovedNodeId = null; + + return NodeVisitor::REMOVE_NODE; + } + + return $this->nodesToReturn[$objectId] ?? $node; + } +} diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index 789560ff739..f0844e7367c 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -15,7 +15,6 @@ use PhpParser\Node\Stmt\Property; use PhpParser\Node\Stmt\Trait_; use PhpParser\NodeVisitor; -use PhpParser\NodeVisitorAbstract; use PHPStan\Analyser\MutatingScope; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -33,10 +32,11 @@ use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; use Rector\PhpParser\Comparing\NodeComparator; use Rector\PhpParser\Node\NodeFactory; +use Rector\PhpParser\NodeVisitor\AbstractLeaveNode; use Rector\Skipper\Skipper\Skipper; use Rector\ValueObject\Application\File; -abstract class AbstractRector extends NodeVisitorAbstract implements RectorInterface +abstract class AbstractRector extends AbstractLeaveNode implements RectorInterface { /** * @var string @@ -71,15 +71,8 @@ abstract class AbstractRector extends NodeVisitorAbstract implements RectorInter private CurrentFileProvider $currentFileProvider; - /** - * @var array - */ - private array $nodesToReturn = []; - private CreatedByRuleDecorator $createdByRuleDecorator; - private ?int $toBeRemovedNodeId = null; - public function autowire( NodeNameResolver $nodeNameResolver, NodeTypeResolver $nodeTypeResolver, @@ -186,31 +179,6 @@ final public function enterNode(Node $node): int|Node|null return $this->postRefactorProcess($originalNode, $node, $refactoredNode, $filePath); } - /** - * Replacing nodes in leaveNode() method avoids infinite recursion - * see"infinite recursion" in https://github.com/nikic/PHP-Parser/blob/master/doc/component/Walking_the_AST.markdown - */ - final public function leaveNode(Node $node): array|int|Node|null - { - if ($node->hasAttribute(AttributeKey::ORIGINAL_NODE)) { - return null; - } - - // nothing to change here - if ($this->toBeRemovedNodeId === null && $this->nodesToReturn === []) { - return null; - } - - $objectId = spl_object_id($node); - if ($this->toBeRemovedNodeId === $objectId) { - $this->toBeRemovedNodeId = null; - - return NodeVisitor::REMOVE_NODE; - } - - return $this->nodesToReturn[$objectId] ?? $node; - } - protected function isName(Node $node, string $name): bool { return $this->nodeNameResolver->isName($node, $name);