|
8 | 8 | use PhpParser\Node\FunctionLike; |
9 | 9 | use PhpParser\Node\Name; |
10 | 10 | use PhpParser\Node\PropertyItem; |
11 | | -use PhpParser\Node\Stmt\Class_; |
12 | 11 | use PhpParser\Node\Stmt\ClassMethod; |
13 | 12 | use PhpParser\Node\Stmt\Const_; |
14 | 13 | use PhpParser\Node\Stmt\InlineHTML; |
|
25 | 24 | use Rector\Application\Provider\CurrentFileProvider; |
26 | 25 | use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; |
27 | 26 | use Rector\ChangesReporting\ValueObject\RectorWithLineChange; |
| 27 | +use Rector\Contract\PhpParser\Node\StmtsAwareInterface; |
28 | 28 | use Rector\Contract\Rector\HTMLAverseRectorInterface; |
29 | 29 | use Rector\Contract\Rector\RectorInterface; |
30 | 30 | use Rector\Exception\ShouldNotHappenException; |
@@ -299,31 +299,34 @@ protected function mirrorComments(Node $newNode, Node $oldNode): void |
299 | 299 |
|
300 | 300 | private function decorateCurrentAndChildren(Node $node): void |
301 | 301 | { |
302 | | - $node->setAttribute(AttributeKey::SKIPPED_BY_RECTOR_RULE, static::class); |
303 | | - |
304 | 302 | // filter only types that |
305 | 303 | // 1. registered in getNodesTypes() method |
306 | 304 | // 2. different with current node type, as already decorated above |
307 | 305 | // |
| 306 | + $types = $this->getNodeTypes(); |
308 | 307 | $otherTypes = array_filter( |
309 | | - $this->getNodeTypes(), |
| 308 | + $types, |
310 | 309 | static fn (string $nodeType): bool => $nodeType !== $node::class |
311 | 310 | ); |
312 | 311 |
|
313 | | - $this->traverseNodesWithCallable($node, static function (Node $subNode) use ($node, $otherTypes): null|int|Node { |
314 | | - // early check here as included in other types defined in getNodeTypes() |
315 | | - if (in_array($subNode::class, $otherTypes, true)) { |
| 312 | + $isCurrentNode = false; |
| 313 | + $this->traverseNodesWithCallable($node, static function (Node $subNode) use ($node, $types, $otherTypes, &$isCurrentNode): int|Node { |
| 314 | + // first visited is current node itself |
| 315 | + if (! $isCurrentNode) { |
| 316 | + $isCurrentNode = true; |
316 | 317 | $subNode->setAttribute(AttributeKey::SKIPPED_BY_RECTOR_RULE, static::class); |
317 | 318 | return $subNode; |
318 | 319 | } |
319 | 320 |
|
320 | | - // already set |
321 | | - if ($node === $subNode) { |
322 | | - return null; |
| 321 | + // early check here as included in other types defined in getNodeTypes() |
| 322 | + if (in_array($subNode::class, $otherTypes, true)) { |
| 323 | + $subNode->setAttribute(AttributeKey::SKIPPED_BY_RECTOR_RULE, static::class); |
| 324 | + return $subNode; |
323 | 325 | } |
324 | 326 |
|
325 | | - // inner class/function are out of scope |
326 | | - if ($subNode instanceof Class_ || $subNode instanceof FunctionLike) { |
| 327 | + // exact StmtsAwareInterface will be visited by itself, and requires revalidated |
| 328 | + // no need to apply skip by current rule |
| 329 | + if ($types === [StmtsAwareInterface::class] && $node instanceof FunctionLike && $subNode instanceof FunctionLike) { |
327 | 330 | return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; |
328 | 331 | } |
329 | 332 |
|
|
0 commit comments