1414use PhpParser \Node \Stmt \Nop ;
1515use PhpParser \Node \Stmt \Property ;
1616use PhpParser \Node \Stmt \Trait_ ;
17+ use PhpParser \NodeTraverser ;
1718use PhpParser \NodeVisitor ;
1819use PhpParser \NodeVisitorAbstract ;
1920use PHPStan \Analyser \MutatingScope ;
@@ -120,6 +121,9 @@ public function beforeTraverse(array $nodes): ?array
120121 return null ;
121122 }
122123
124+ /**
125+ * @return NodeTraverser::REMOVE_NODE|Node|null
126+ */
123127 final public function enterNode (Node $ node ): int |Node |null
124128 {
125129 if (! $ this ->isMatchingNodeType ($ node )) {
@@ -138,57 +142,47 @@ final public function enterNode(Node $node): int|Node|null
138142 // ensure origNode pulled before refactor to avoid changed during refactor, ref https://3v4l.org/YMEGN
139143 $ originalNode = $ node ->getAttribute (AttributeKey::ORIGINAL_NODE ) ?? $ node ;
140144
141- $ refactoredNode = $ this ->refactor ($ node );
145+ $ refactoredNodeOrState = $ this ->refactor ($ node );
142146
143147 // nothing to change → continue
144- if ($ refactoredNode === null ) {
148+ if ($ refactoredNodeOrState === null ) {
145149 return null ;
146150 }
147151
148- if ($ refactoredNode === []) {
152+ if ($ refactoredNodeOrState === []) {
149153 $ errorMessage = sprintf (self ::EMPTY_NODE_ARRAY_MESSAGE , static ::class);
150154 throw new ShouldNotHappenException ($ errorMessage );
151155 }
152156
153- $ isIntRefactoredNode = is_int ($ refactoredNode );
157+ $ isState = is_int ($ refactoredNodeOrState );
154158
155- /**
156- * If below node and/or its children not traversed on current rule
157- * early return null with decorate current and children node with skipped by "only" current rule
158- */
159- if ($ isIntRefactoredNode ) {
159+ if ($ isState ) {
160160 $ this ->createdByRuleDecorator ->decorate ($ node , $ originalNode , static ::class);
161161
162- if (in_array (
163- $ refactoredNode ,
164- [NodeVisitor::DONT_TRAVERSE_CHILDREN , NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN ],
165- true
166- )) {
167- $ this ->decorateCurrentAndChildren ($ node );
162+ // only remove node is supported
163+ if ($ refactoredNodeOrState !== NodeVisitor::REMOVE_NODE ) {
168164 return null ;
169165 }
170166
171- // @see NodeVisitor::* codes, e.g. removal of node of stopping the traversing
172- if ($ refactoredNode === NodeVisitor::REMOVE_NODE ) {
173- // log here, so we can remove the node in leaveNode() method
174- $ this ->toBeRemovedNodeId = spl_object_id ($ originalNode );
175- }
167+ // log here, so we can remove the node in leaveNode() method
168+ $ this ->toBeRemovedNodeId = spl_object_id ($ originalNode );
176169
177- // notify this rule changing code
170+ // notify this rule changed code
178171 $ rectorWithLineChange = new RectorWithLineChange (static ::class, $ originalNode ->getStartLine ());
179172 $ this ->file ->addRectorClassWithLine ($ rectorWithLineChange );
180173
181- return $ refactoredNode === NodeVisitor::REMOVE_NODE
182- ? $ originalNode
183- : $ refactoredNode ;
174+ // keep original node as node will be removed in leaveNode()
175+ return $ originalNode ;
184176 }
185177
186- return $ this ->postRefactorProcess ($ originalNode , $ node , $ refactoredNode , $ filePath );
178+ return $ this ->postRefactorProcess ($ originalNode , $ node , $ refactoredNodeOrState , $ filePath );
187179 }
188180
189181 /**
190182 * Replacing nodes in leaveNode() method avoids infinite recursion
191183 * see"infinite recursion" in https://github.com/nikic/PHP-Parser/blob/master/doc/component/Walking_the_AST.markdown
184+ *
185+ * @return \PhpParser\Node|\PhpParser\Node[]|NodeVisitor::REMOVE_NODE|null
192186 */
193187 final public function leaveNode (Node $ node ): array |int |Node |null
194188 {
@@ -295,35 +289,6 @@ protected function mirrorComments(Node $newNode, Node $oldNode): void
295289 }
296290 }
297291
298- private function decorateCurrentAndChildren (Node $ node ): void
299- {
300- // skip sole type, as no other nodes to filter out
301- if (count ($ this ->getNodeTypes ()) === 1 ) {
302- return ;
303- }
304-
305- // filter only types that
306- // 1. registered in getNodesTypes() method
307- // 2. different with current node type, as already decorated above
308- //
309- $ otherTypes = array_filter (
310- $ this ->getNodeTypes (),
311- static fn (string $ nodeType ): bool => $ nodeType !== $ node ::class
312- );
313-
314- if ($ otherTypes === []) {
315- return ;
316- }
317-
318- $ this ->traverseNodesWithCallable ($ node , static function (Node $ subNode ) use ($ otherTypes ): null {
319- if (in_array ($ subNode ::class, $ otherTypes , true )) {
320- $ subNode ->setAttribute (AttributeKey::SKIPPED_BY_RECTOR_RULE , static ::class);
321- }
322-
323- return null ;
324- });
325- }
326-
327292 /**
328293 * @param Node|Node[] $refactoredNode
329294 */
0 commit comments