1919use Webmozart \Assert \Assert ;
2020
2121/**
22+ * Based on native NodeTraverser class, but heavily customized for Rector needs.
23+ *
24+ * The main differences are:
25+ * - no leaveNode(), as we do all in enterNode() that calls refactor() method
26+ * - cached visitors per node class for performance, e.g. when we find rules for Class_ node, they're cached for next time
27+ * - immutability features, register Rector rules once, then use; no changes on the fly
2228 * @see \Rector\Tests\PhpParser\NodeTraverser\RectorNodeTraverserTest
2329 */
2430final class RectorNodeTraverser implements NodeTraverserInterface
@@ -33,7 +39,7 @@ final class RectorNodeTraverser implements NodeTraverserInterface
3339 private bool $ areNodeVisitorsPrepared = false ;
3440
3541 /**
36- * @var array<class-string<Node>, NodeVisitor []>
42+ * @var array<class-string<Node>, RectorInterface []>
3743 */
3844 private array $ visitorsPerNodeClass = [];
3945
@@ -103,26 +109,30 @@ public function refreshPhpRectors(array $rectors): void
103109 }
104110
105111 /**
106- * @return NodeVisitor[]
112+ * @api used in tests
113+ * @return RectorInterface[]
107114 */
108115 public function getVisitorsForNode (Node $ node ): array
109116 {
110117 $ nodeClass = $ node ::class;
111118
119+ if (! $ this ->areNodeVisitorsPrepared ) {
120+ $ this ->prepareNodeVisitors ();
121+ }
122+
112123 if (! isset ($ this ->visitorsPerNodeClass [$ nodeClass ])) {
113124 $ this ->visitorsPerNodeClass [$ nodeClass ] = [];
114125
115- /** @var RectorInterface $visitor */
116- foreach ($ this ->visitors as $ visitor ) {
117- foreach ($ visitor ->getNodeTypes () as $ nodeType ) {
126+ foreach ($ this ->rectors as $ rector ) {
127+ foreach ($ rector ->getNodeTypes () as $ nodeType ) {
118128 // BC layer matching
119129 if ($ nodeType === FileWithoutNamespace::class && $ nodeClass === FileNode::class) {
120- $ this ->visitorsPerNodeClass [$ nodeClass ][] = $ visitor ;
130+ $ this ->visitorsPerNodeClass [$ nodeClass ][] = $ rector ;
121131 continue ;
122132 }
123133
124134 if (is_a ($ nodeClass , $ nodeType , true )) {
125- $ this ->visitorsPerNodeClass [$ nodeClass ][] = $ visitor ;
135+ $ this ->visitorsPerNodeClass [$ nodeClass ][] = $ rector ;
126136 continue 2 ;
127137 }
128138 }
0 commit comments