diff --git a/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php b/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php index 263d194d155..52f8172f319 100644 --- a/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php +++ b/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php @@ -142,7 +142,7 @@ public function refactor(Node $node): ?Node return null; } - /** @var Expression $previousStmt */ + /** @var Assign|AssignOp $assign */ $assign = $previousStmt->expr; return $this->processSimplifyUselessVariable($node, $stmt, $assign, $key); diff --git a/rules/CodeQuality/Rector/If_/SimplifyIfElseToTernaryRector.php b/rules/CodeQuality/Rector/If_/SimplifyIfElseToTernaryRector.php index 449af2cdc22..c3e4ae3aab7 100644 --- a/rules/CodeQuality/Rector/If_/SimplifyIfElseToTernaryRector.php +++ b/rules/CodeQuality/Rector/If_/SimplifyIfElseToTernaryRector.php @@ -81,7 +81,7 @@ public function getNodeTypes(): array /** * @param If_ $node */ - public function refactor(Node $node): ?Node + public function refactor(Node $node): ?Expression { if (! $node->else instanceof Else_) { return null; diff --git a/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php b/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php index 0aeea1d7918..a2a558b3666 100644 --- a/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php @@ -13,26 +13,6 @@ abstract class AbstractImmutableNodeTraverser implements NodeTraverserInterface { - /** - * @deprecated Use NodeVisitor::DONT_TRAVERSE_CHILDREN instead. - */ - public const DONT_TRAVERSE_CHILDREN = NodeVisitor::DONT_TRAVERSE_CHILDREN; - - /** - * @deprecated Use NodeVisitor::STOP_TRAVERSAL instead. - */ - public const STOP_TRAVERSAL = NodeVisitor::STOP_TRAVERSAL; - - /** - * @deprecated Use NodeVisitor::REMOVE_NODE instead. - */ - public const REMOVE_NODE = NodeVisitor::REMOVE_NODE; - - /** - * @deprecated Use NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN instead. - */ - public const DONT_TRAVERSE_CURRENT_AND_CHILDREN = NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; - /** * @var list Visitors */ @@ -131,13 +111,22 @@ protected function traverseNode(Node $node): void $traverseChildren = true; $visitorIndex = -1; $currentNodeVisitors = $this->getVisitorsForNode($subNode); + foreach ($currentNodeVisitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($subNode); if ($return !== null) { if ($return instanceof Node) { + + $originalNodeClass = $subNode::class; + $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; $node->{$name} = $return; + + if ($originalNodeClass !== $return::class) { + $traverseChildren = false; + break; + } } elseif ($return === NodeVisitor::DONT_TRAVERSE_CHILDREN) { $traverseChildren = false; } elseif ($return === NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { @@ -210,12 +199,21 @@ protected function traverseArray(array $nodes): array $traverseChildren = true; $visitorIndex = -1; $currentNodeVisitors = $this->getVisitorsForNode($node); + foreach ($currentNodeVisitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if ($return !== null) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); + + // hos node type changed? + $originalNodeCLass = $node::class; $nodes[$i] = $node = $return; + + if ($originalNodeCLass !== $return::class) { + $traverseChildren = false; + break; + } } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; continue 2; diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index abcc15b6662..f8cca3bc0ba 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -128,9 +128,11 @@ public function beforeTraverse(array $nodes): ?array */ final public function enterNode(Node $node): int|Node|null { - if (! $this->isMatchingNodeType($node)) { - return null; - } + // if previous Rector rule changed the node type, we have to skip it here + // as here we expect still the original type + // if (! $this->isMatchingNodeType($node)) { + // return null; + //} if (is_a($this, HTMLAverseRectorInterface::class, true) && $this->file->containsHTML()) { return null; @@ -319,16 +321,4 @@ private function refreshScopeNodes(array | Node $node, string $filePath, ?Mutati $this->changedNodeScopeRefresher->refresh($node, $filePath, $mutatingScope); } } - - private function isMatchingNodeType(Node $node): bool - { - $nodeClass = $node::class; - foreach ($this->getNodeTypes() as $nodeType) { - if (is_a($nodeClass, $nodeType, true)) { - return true; - } - } - - return false; - } } diff --git a/tests/Issues/SimplifyVariableIfElseTernary/config/configured_rule.php b/tests/Issues/SimplifyVariableIfElseTernary/config/configured_rule.php index a49cb9a6ad7..4b22f5d7fd3 100644 --- a/tests/Issues/SimplifyVariableIfElseTernary/config/configured_rule.php +++ b/tests/Issues/SimplifyVariableIfElseTernary/config/configured_rule.php @@ -8,10 +8,8 @@ use Rector\Config\RectorConfig; return RectorConfig::configure() - ->withRules( - [ - SimplifyIfElseToTernaryRector::class, - SimplifyUselessVariableRector::class, - CompleteDynamicPropertiesRector::class, - ] - ); + ->withRules([ + SimplifyIfElseToTernaryRector::class, + SimplifyUselessVariableRector::class, + CompleteDynamicPropertiesRector::class, + ]);