diff --git a/composer.json b/composer.json index ca495d81f38..a9096fe472e 100644 --- a/composer.json +++ b/composer.json @@ -118,23 +118,6 @@ "patches": { "illuminate/container": [ "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/illuminate-container-container-php.patch" - ], - "nikic/php-parser": [ - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-expr-closure-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-finally-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-function-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-do-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-catch-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-trycatch-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-for-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-classmethod-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-else-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-while-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-foreach-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-if-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-case-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-elseif-php.patch", - "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/nikic-php-parser-lib-phpparser-node-stmt-namespace-php.patch" ] }, "composer-exit-on-patch-failure": true, diff --git a/phpstan.neon b/phpstan.neon index 0258b5d11d2..f075dd87764 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -376,3 +376,12 @@ parameters: - message: '#Property Rector\\PhpParser\\NodeTraverser\\AbstractImmutableNodeTraverser\:\:\$visitors \(list\) does not accept array#' path: src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php + + # special check for stmts aware virtual interface + - + path: src/PhpParser/NodeTraverser/RectorNodeTraverser.php + identifier: symplify.forbiddenFuncCall + - '#Parameter \d should use "Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface" type as the only type passed to this method#' + - '#Parameter \#1 \$stmtsAware of method (.*?) expects Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface#' + + - '#Method (.*?) should return Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface\|null but returns (.*?)\|null#' diff --git a/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php b/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php index 0f9714edbac..2b116c739de 100644 --- a/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php +++ b/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.php @@ -24,6 +24,7 @@ use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector\SimplifyUselessVariableRectorTest @@ -151,12 +152,18 @@ public function refactor(Node $node): ?Node return null; } + /** + * @param StmtsAwareInterface $stmtsAware + * @return StmtsAwareInterface + */ private function processSimplifyUselessVariable( - StmtsAwareInterface $stmtsAware, + \PhpParser\Node $stmtsAware, Return_ $return, Assign|AssignOp $assign, int $key - ): ?StmtsAwareInterface { + ): \PhpParser\Node|null { + Assert::propertyExists($stmtsAware, 'stmts'); + if (! $assign instanceof Assign) { $binaryClass = $this->assignAndBinaryMap->getAlternative($assign); if ($binaryClass === null) { diff --git a/rules/CodeQuality/Rector/If_/SimplifyIfNotNullReturnRector.php b/rules/CodeQuality/Rector/If_/SimplifyIfNotNullReturnRector.php index 48c0b83880f..2644290c482 100644 --- a/rules/CodeQuality/Rector/If_/SimplifyIfNotNullReturnRector.php +++ b/rules/CodeQuality/Rector/If_/SimplifyIfNotNullReturnRector.php @@ -62,7 +62,7 @@ public function getNodeTypes(): array /** * @param StmtsAwareInterface $node */ - public function refactor(Node $node): ?StmtsAwareInterface + public function refactor(Node $node): ?\PhpParser\Node { foreach ((array) $node->stmts as $key => $stmt) { if (! $stmt instanceof If_) { diff --git a/rules/CodeQuality/Rector/If_/SimplifyIfReturnBoolRector.php b/rules/CodeQuality/Rector/If_/SimplifyIfReturnBoolRector.php index 12d21ee35f6..65d9ffaacf5 100644 --- a/rules/CodeQuality/Rector/If_/SimplifyIfReturnBoolRector.php +++ b/rules/CodeQuality/Rector/If_/SimplifyIfReturnBoolRector.php @@ -76,6 +76,10 @@ public function refactor(Node $node): ?Node } foreach ($node->stmts as $key => $stmt) { + if ($key === 0) { + continue; + } + if (! $stmt instanceof Return_) { continue; } diff --git a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php index 0417e173d4a..b77d76fcae2 100644 --- a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php +++ b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php @@ -25,9 +25,11 @@ use Rector\NodeManipulator\StmtsManipulator; use Rector\Php\ReservedKeywordAnalyzer; use Rector\PhpParser\Node\BetterNodeFinder; +use Rector\PhpParser\NodeGroups; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\DeadCode\Rector\Assign\RemoveUnusedVariableAssignRector\RemoveUnusedVariableAssignRectorTest @@ -164,10 +166,12 @@ private function shouldSkip(array $stmts): bool */ private function collectAssignRefVariableNames(Stmt $stmt, array &$refVariableNames): void { - if (! $stmt instanceof StmtsAwareInterface) { + if (! NodeGroups::matchesStmtsAware($stmt)) { return; } + Assert::propertyExists($stmt, 'stmts'); + $this->traverseNodesWithCallable( $stmt, function (Node $subNode) use (&$refVariableNames): Node { diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php index 89ab3af618e..6910c71b7d8 100644 --- a/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php +++ b/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.php @@ -78,7 +78,25 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { +<<<<<<< HEAD if ($node->getMethods() === []) { +======= + foreach ($node->stmts as $stmt) { + if (!$stmt instanceof ClassMethod) { + continue; + } + + if ($stmt->isPrivate()) { + return null; + } + + dump('todo'); + } + + $classMethods = $node->getMethods(); + + if ($classMethods === []) { +>>>>>>> 77e904a598 (flip keys) return null; } diff --git a/rules/DeadCode/Rector/For_/RemoveDeadIfForeachForRector.php b/rules/DeadCode/Rector/For_/RemoveDeadIfForeachForRector.php index da26f962428..68ca6d3d183 100644 --- a/rules/DeadCode/Rector/For_/RemoveDeadIfForeachForRector.php +++ b/rules/DeadCode/Rector/For_/RemoveDeadIfForeachForRector.php @@ -113,7 +113,10 @@ public function refactor(Node $node): Node|null return null; } - private function processIf(If_ $if, int $key, StmtsAwareInterface $stmtsAware): void + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function processIf(If_ $if, int $key, \PhpParser\Node $stmtsAware): void { if ($if->elseifs !== []) { return; @@ -137,7 +140,10 @@ private function processIf(If_ $if, int $key, StmtsAwareInterface $stmtsAware): $this->hasChanged = true; } - private function processForForeach(For_|Foreach_ $for, int $key, StmtsAwareInterface $stmtsAware): void + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function processForForeach(For_|Foreach_ $for, int $key, \PhpParser\Node $stmtsAware): void { if ($for instanceof For_) { $variables = $this->betterNodeFinder->findInstanceOf( diff --git a/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php b/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php index d328de2e17c..97a8c549ce2 100644 --- a/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php +++ b/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php @@ -25,6 +25,7 @@ use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\DeadCode\Rector\If_\RemoveUnusedNonEmptyArrayBeforeForeachRector\RemoveUnusedNonEmptyArrayBeforeForeachRectorTest @@ -83,12 +84,12 @@ public function run() */ public function getNodeTypes(): array { - return [If_::class, StmtsAwareInterface::class]; + return [StmtsAwareInterface::class]; } /** - * @param If_|StmtsAwareInterface $node - * @return Foreach_|StmtsAwareInterface|null + * @param StmtsAwareInterface $node + * @return StmtsAwareInterface|null */ public function refactor(Node $node): Node|null { @@ -151,8 +152,13 @@ private function isUselessBooleanAnd(BooleanAnd $booleanAnd, Expr $foreachExpr): return $this->countManipulator->isCounterHigherThanOne($booleanAnd->right, $foreachExpr); } - private function refactorStmtsAware(StmtsAwareInterface $stmtsAware): ?StmtsAwareInterface + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function refactorStmtsAware(\PhpParser\Node $stmtsAware): ?StmtsAwareInterface { + Assert::propertyExists($stmtsAware, 'stmts'); + if ($stmtsAware->stmts === null) { return null; } diff --git a/rules/EarlyReturn/Rector/Return_/PreparedValueToEarlyReturnRector.php b/rules/EarlyReturn/Rector/Return_/PreparedValueToEarlyReturnRector.php index 12d07352976..394fcaed586 100644 --- a/rules/EarlyReturn/Rector/Return_/PreparedValueToEarlyReturnRector.php +++ b/rules/EarlyReturn/Rector/Return_/PreparedValueToEarlyReturnRector.php @@ -183,9 +183,11 @@ public function refactor(Node $node): ?StmtsAwareInterface /** * @param If_[] $ifs + * @param StmtsAwareInterface $stmtsAware + * * @return BareSingleAssignIf[] */ - private function getMatchingBareSingleAssignIfs(array $ifs, StmtsAwareInterface $stmtsAware): array + private function getMatchingBareSingleAssignIfs(array $ifs, \PhpParser\Node $stmtsAware): array { $bareSingleAssignIfs = []; foreach ($ifs as $key => $if) { @@ -233,7 +235,10 @@ private function isVariableSharedInAssignIfsAndReturn( return true; } - private function matchBareSingleAssignIf(Stmt $stmt, int $key, StmtsAwareInterface $stmtsAware): ?BareSingleAssignIf + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function matchBareSingleAssignIf(Stmt $stmt, int $key, \PhpParser\Node $stmtsAware): ?BareSingleAssignIf { if (! $stmt instanceof If_) { return null; diff --git a/rules/Php84/Rector/Foreach_/ForeachToArrayAllRector.php b/rules/Php84/Rector/Foreach_/ForeachToArrayAllRector.php index 07cdc3ecd5f..ddd8d9ed3cd 100644 --- a/rules/Php84/Rector/Foreach_/ForeachToArrayAllRector.php +++ b/rules/Php84/Rector/Foreach_/ForeachToArrayAllRector.php @@ -25,6 +25,7 @@ use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\Php84\Rector\Foreach_\ForeachToArrayAllRector\ForeachToArrayAllRectorTest @@ -102,8 +103,13 @@ public function provideMinPhpVersion(): int return PhpVersionFeature::ARRAY_ALL; } - private function refactorBooleanAssignmentPattern(StmtsAwareInterface $stmtsAware): ?Node + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function refactorBooleanAssignmentPattern(\PhpParser\Node $stmtsAware): ?Node { + Assert::propertyExists($stmtsAware, 'stmts'); + foreach ($stmtsAware->stmts as $key => $stmt) { if (! $stmt instanceof Foreach_) { continue; @@ -185,8 +191,13 @@ private function refactorBooleanAssignmentPattern(StmtsAwareInterface $stmtsAwar return null; } - private function refactorEarlyReturnPattern(StmtsAwareInterface $stmtsAware): ?Node + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function refactorEarlyReturnPattern(\PhpParser\Node $stmtsAware): ?Node { + Assert::propertyExists($stmtsAware, 'stmts'); + foreach ($stmtsAware->stmts as $key => $stmt) { if (! $stmt instanceof Foreach_) { continue; diff --git a/rules/Php84/Rector/Foreach_/ForeachToArrayAnyRector.php b/rules/Php84/Rector/Foreach_/ForeachToArrayAnyRector.php index 9ddea5d90c2..317b0513e41 100644 --- a/rules/Php84/Rector/Foreach_/ForeachToArrayAnyRector.php +++ b/rules/Php84/Rector/Foreach_/ForeachToArrayAnyRector.php @@ -24,6 +24,7 @@ use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\Php84\Rector\Foreach_\ForeachToArrayAnyRector\ForeachToArrayAnyRectorTest @@ -101,8 +102,13 @@ public function provideMinPhpVersion(): int return PhpVersionFeature::ARRAY_ANY; } - private function refactorBooleanAssignmentPattern(StmtsAwareInterface $stmtsAware): ?Node + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function refactorBooleanAssignmentPattern(\PhpParser\Node $stmtsAware): ?Node { + Assert::propertyExists($stmtsAware, 'stmts'); + foreach ($stmtsAware->stmts as $key => $stmt) { if (! $stmt instanceof Foreach_) { continue; @@ -182,8 +188,13 @@ private function refactorBooleanAssignmentPattern(StmtsAwareInterface $stmtsAwar return null; } - private function refactorEarlyReturnPattern(StmtsAwareInterface $stmtsAware): ?Node + /** + * @param StmtsAwareInterface $stmtsAware + */ + private function refactorEarlyReturnPattern(\PhpParser\Node $stmtsAware): ?Node { + Assert::propertyExists($stmtsAware, 'stmts'); + foreach ($stmtsAware->stmts as $key => $stmt) { if (! $stmt instanceof Foreach_) { continue; diff --git a/src/NodeManipulator/StmtsManipulator.php b/src/NodeManipulator/StmtsManipulator.php index eb018b2c1b1..fadbf2339af 100644 --- a/src/NodeManipulator/StmtsManipulator.php +++ b/src/NodeManipulator/StmtsManipulator.php @@ -18,6 +18,7 @@ use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; use Rector\PhpParser\Comparing\NodeComparator; use Rector\PhpParser\Node\BetterNodeFinder; +use Webmozart\Assert\Assert; final readonly class StmtsManipulator { @@ -73,11 +74,13 @@ function (Node $node) use (&$stmts): null { return $stmts; } - public function isVariableUsedInNextStmt( - StmtsAwareInterface $stmtsAware, - int $jumpToKey, - string $variableName - ): bool { + /** + * @param StmtsAwareInterface $stmtsAware + */ + public function isVariableUsedInNextStmt(Node $stmtsAware, int $jumpToKey, string $variableName): bool + { + Assert::propertyExists($stmtsAware, 'stmts'); + if ($stmtsAware->stmts === null) { return false; } diff --git a/src/NodeTypeResolver/Node/AttributeKey.php b/src/NodeTypeResolver/Node/AttributeKey.php index b5395a2d35b..ad2f4705657 100644 --- a/src/NodeTypeResolver/Node/AttributeKey.php +++ b/src/NodeTypeResolver/Node/AttributeKey.php @@ -162,8 +162,12 @@ final class AttributeKey public const IS_BYREF_RETURN = 'is_byref_return'; /** +<<<<<<< HEAD * @deprecated This value can change, as based on default input keys. Use existing array keys instead. * +======= + * @deprecated use keys directly from stmts iteration as convention +>>>>>>> c23994b233 (note) * @var string */ public const STMT_KEY = 'stmt_key'; diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php index 1e3c096b2f3..893dcdeb787 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php @@ -12,10 +12,11 @@ use PhpParser\Node\Stmt\Global_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; -use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; +use Rector\PhpParser\NodeGroups; +use Webmozart\Assert\Assert; final class GlobalVariableNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface { @@ -26,10 +27,12 @@ public function __construct( public function enterNode(Node $node): ?Node { - if (! $node instanceof StmtsAwareInterface) { + if (! NodeGroups::matchesStmtsAware($node)) { return null; } + Assert::propertyExists($node, 'stmts'); + if ($node->stmts === null) { return null; } diff --git a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php index fa3556bf986..7f8688ec52f 100644 --- a/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php +++ b/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php @@ -12,10 +12,11 @@ use PhpParser\Node\Stmt\Static_; use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; -use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Scope\Contract\NodeVisitor\ScopeResolverNodeVisitorInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; +use Rector\PhpParser\NodeGroups; +use Webmozart\Assert\Assert; final class StaticVariableNodeVisitor extends NodeVisitorAbstract implements ScopeResolverNodeVisitorInterface { @@ -26,10 +27,12 @@ public function __construct( public function enterNode(Node $node): ?Node { - if (! $node instanceof StmtsAwareInterface) { + if (! NodeGroups::matchesStmtsAware($node)) { return null; } + Assert::propertyExists($node, 'stmts'); + if ($node->stmts === null) { return null; } diff --git a/src/PhpParser/NodeGroups.php b/src/PhpParser/NodeGroups.php new file mode 100644 index 00000000000..b99ed2dd01d --- /dev/null +++ b/src/PhpParser/NodeGroups.php @@ -0,0 +1,45 @@ +> + */ + public const STMTS_AWARE_NODES = [ + \PhpParser\Node\Expr\Closure::class, + \PhpParser\Node\Stmt\Block::class, + \PhpParser\Node\Stmt\Case_::class, + \PhpParser\Node\Stmt\Catch_::class, + \PhpParser\Node\Stmt\ClassMethod::class, + \PhpParser\Node\Stmt\Do_::class, + \PhpParser\Node\Stmt\ElseIf_::class, + \PhpParser\Node\Stmt\Else_::class, + \PhpParser\Node\Stmt\Finally_::class, + \PhpParser\Node\Stmt\For_::class, + \PhpParser\Node\Stmt\Foreach_::class, + \PhpParser\Node\Stmt\Function_::class, + \PhpParser\Node\Stmt\If_::class, + \PhpParser\Node\Stmt\Namespace_::class, + \PhpParser\Node\Stmt\TryCatch::class, + \PhpParser\Node\Stmt\While_::class, + // custom Rector node + FileWithoutNamespace::class, + ]; + + public static function matchesStmtsAware(\PhpParser\Node $node): bool + { + foreach (self::STMTS_AWARE_NODES as $stmtAwareNodeClass) { + if (is_a($node, $stmtAwareNodeClass)) { + return true; + } + } + + return false; + } +} diff --git a/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php b/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php index 0aeea1d7918..4b8bb40fd49 100644 --- a/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/AbstractImmutableNodeTraverser.php @@ -210,6 +210,8 @@ protected function traverseArray(array $nodes): array $traverseChildren = true; $visitorIndex = -1; $currentNodeVisitors = $this->getVisitorsForNode($node); + + // @todo change everything we dont need here foreach ($currentNodeVisitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if ($return !== null) { diff --git a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php index f80922a89bc..8fb4afda29d 100644 --- a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php @@ -8,7 +8,9 @@ use PhpParser\Node\Stmt; use PhpParser\NodeVisitor; use Rector\Configuration\ConfigurationRuleFilter; +use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\Contract\Rector\RectorInterface; +use Rector\PhpParser\NodeGroups; use Rector\VersionBonding\PhpVersionedFilter; /** @@ -67,9 +69,21 @@ public function getVisitorsForNode(Node $node): array if (! isset($this->visitorsPerNodeClass[$nodeClass])) { $this->visitorsPerNodeClass[$nodeClass] = []; + /** @var RectorInterface $visitor */ + foreach ($this->visitors as $visitor) { foreach ($visitor->getNodeTypes() as $nodeType) { + // special case for StmtsAwareInterface + if ($nodeType === StmtsAwareInterface::class && property_exists($node, 'stmts')) { + // all stmts are node classes + foreach (NodeGroups::STMTS_AWARE_NODES as $stmtsAwareNodeClass) { + $this->visitorsPerNodeClass[$stmtsAwareNodeClass][] = $visitor; + } + + continue 2; + } + if (is_a($nodeClass, $nodeType, true)) { $this->visitorsPerNodeClass[$nodeClass][] = $visitor; continue 2; diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index 789560ff739..cd8fcd2b05d 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -23,6 +23,7 @@ use Rector\Application\Provider\CurrentFileProvider; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\ChangesReporting\ValueObject\RectorWithLineChange; +use Rector\Contract\PhpParser\Node\StmtsAwareInterface; use Rector\Contract\Rector\HTMLAverseRectorInterface; use Rector\Contract\Rector\RectorInterface; use Rector\Exception\ShouldNotHappenException; @@ -33,6 +34,7 @@ use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; use Rector\PhpParser\Comparing\NodeComparator; use Rector\PhpParser\Node\NodeFactory; +use Rector\PhpParser\NodeGroups; use Rector\Skipper\Skipper\Skipper; use Rector\ValueObject\Application\File; @@ -375,6 +377,14 @@ private function isMatchingNodeType(Node $node): bool { $nodeClass = $node::class; foreach ($this->getNodeTypes() as $nodeType) { + if ($nodeType === StmtsAwareInterface::class) { + foreach (NodeGroups::STMTS_AWARE_NODES as $stmtsAwareNodeClass) { + if (is_a($nodeClass, $stmtsAwareNodeClass, true)) { + return true; + } + } + } + if (is_a($nodeClass, $nodeType, true)) { return true; }