Skip to content

Commit 93b6d13

Browse files
committed
Remove dont traverse int return from ChangeSwitchToMatchRector
1 parent 1642aea commit 93b6d13

File tree

8 files changed

+77
-52
lines changed

8 files changed

+77
-52
lines changed

phpstan.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,5 +392,4 @@ parameters:
392392
-
393393
identifier: rector.noIntegerRefactorReturn
394394
paths:
395-
- rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php
396395
- tests/Issues/InfiniteLoop/Rector/MethodCall/InfinityLoopRector.php

rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111
use PhpParser\Node\Expr\Cast\Int_;
1212
use PhpParser\Node\Expr\Cast\String_;
1313
use PhpParser\Node\Expr\Match_;
14-
use PhpParser\Node\FunctionLike;
1514
use PhpParser\Node\Stmt\Expression;
1615
use PhpParser\Node\Stmt\Return_;
1716
use PhpParser\Node\Stmt\Switch_;
18-
use PhpParser\NodeVisitor;
1917
use PHPStan\Type\ObjectType;
2018
use Rector\NodeAnalyzer\ExprAnalyzer;
19+
use Rector\NodeTypeResolver\Node\AttributeKey;
2120
use Rector\Php80\NodeAnalyzer\MatchSwitchAnalyzer;
2221
use Rector\Php80\NodeFactory\MatchFactory;
2322
use Rector\Php80\NodeResolver\SwitchExprsResolver;
@@ -83,25 +82,25 @@ public function getNodeTypes(): array
8382

8483
/**
8584
* @param StmtsAware $node
86-
* @return null|Node|NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN
8785
*/
88-
public function refactor(Node $node): null|Node|int
86+
public function refactor(Node $node): null|Node
8987
{
9088
if (! is_array($node->stmts)) {
9189
return null;
9290
}
9391

94-
if ($node instanceof FunctionLike && $node->returnsByRef()) {
95-
return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
96-
}
97-
9892
$hasChanged = false;
9993

10094
foreach ($node->stmts as $key => $stmt) {
10195
if (! $stmt instanceof Switch_) {
10296
continue;
10397
}
10498

99+
// possible reference override, where match
100+
if ($stmt->getAttribute(AttributeKey::IS_INSIDE_BYREF_FUNCTION_LIKE)) {
101+
continue;
102+
}
103+
105104
$nextStmt = $node->stmts[$key + 1] ?? null;
106105

107106
$condAndExprs = $this->switchExprsResolver->resolve($stmt);

src/NodeTypeResolver/Node/AttributeKey.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,6 @@ final class AttributeKey
292292
public const IS_CLASS_CONST_VALUE = 'is_default_class_const_value';
293293

294294
public const IS_INSIDE_SYMFONY_PHP_CLOSURE = 'is_inside_symfony_php_closure';
295+
296+
public const IS_INSIDE_BYREF_FUNCTION_LIKE = 'is_inside_byref_function_like';
295297
}

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface;
1414
use Rector\NodeTypeResolver\Node\AttributeKey;
1515
use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser;
16+
use Rector\PhpParser\NodeTraverser\SimpleNodeTraverser;
1617

1718
final class ByRefReturnNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
1819
{
@@ -36,9 +37,12 @@ public function enterNode(Node $node): ?Node
3637
return null;
3738
}
3839

40+
SimpleNodeTraverser::decorateWithAttributeValue($stmts, AttributeKey::IS_INSIDE_BYREF_FUNCTION_LIKE, true);
41+
3942
$this->simpleCallableNodeTraverser->traverseNodesWithCallable(
4043
$stmts,
4144
static function (Node $node): int|null|Node {
45+
// avoid nested functions or classes
4246
if ($node instanceof Class_ || $node instanceof FunctionLike) {
4347
return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
4448
}

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/PropertyOrClassConstDefaultNodeVisitor.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use PhpParser\NodeVisitorAbstract;
1212
use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface;
1313
use Rector\NodeTypeResolver\Node\AttributeKey;
14-
use Rector\PhpParser\NodeTraverser\SimpleTraverser;
14+
use Rector\PhpParser\NodeTraverser\SimpleNodeTraverser;
1515

1616
final class PropertyOrClassConstDefaultNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
1717
{
@@ -24,13 +24,21 @@ public function enterNode(Node $node): ?Node
2424
continue;
2525
}
2626

27-
SimpleTraverser::decorateWithTrueAttribute($default, AttributeKey::IS_DEFAULT_PROPERTY_VALUE);
27+
SimpleNodeTraverser::decorateWithAttributeValue(
28+
$default,
29+
AttributeKey::IS_DEFAULT_PROPERTY_VALUE,
30+
true
31+
);
2832
}
2933
}
3034

3135
if ($node instanceof ClassConst) {
3236
foreach ($node->consts as $const) {
33-
SimpleTraverser::decorateWithTrueAttribute($const->value, AttributeKey::IS_CLASS_CONST_VALUE);
37+
SimpleNodeTraverser::decorateWithAttributeValue(
38+
$const->value,
39+
AttributeKey::IS_CLASS_CONST_VALUE,
40+
true
41+
);
3442
}
3543
}
3644

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/SymfonyClosureNodeVisitor.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use PhpParser\NodeVisitorAbstract;
1010
use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface;
1111
use Rector\NodeTypeResolver\Node\AttributeKey;
12-
use Rector\PhpParser\NodeTraverser\SimpleTraverser;
12+
use Rector\PhpParser\NodeTraverser\SimpleNodeTraverser;
1313
use Rector\Symfony\NodeAnalyzer\SymfonyPhpClosureDetector;
1414

1515
final class SymfonyClosureNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
@@ -29,7 +29,11 @@ public function enterNode(Node $node): ?Node
2929
return null;
3030
}
3131

32-
SimpleTraverser::decorateWithTrueAttribute($node, AttributeKey::IS_INSIDE_SYMFONY_PHP_CLOSURE);
32+
SimpleNodeTraverser::decorateWithAttributeValue(
33+
(array) $node->stmts,
34+
AttributeKey::IS_INSIDE_SYMFONY_PHP_CLOSURE,
35+
true
36+
);
3337

3438
return null;
3539
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PhpParser\NodeTraverser;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\FunctionLike;
9+
use PhpParser\Node\Stmt\Class_;
10+
use PhpParser\NodeTraverser;
11+
use PhpParser\NodeVisitor;
12+
use PhpParser\NodeVisitorAbstract;
13+
use Rector\NodeTypeResolver\Node\AttributeKey;
14+
15+
final class SimpleNodeTraverser
16+
{
17+
/**
18+
* @param Node[]|Node $nodesOrNode
19+
* @param AttributeKey::* $attributeKey
20+
*/
21+
public static function decorateWithAttributeValue(array|Node $nodesOrNode, string $attributeKey, mixed $value): void
22+
{
23+
$callableNodeVisitor = new class($attributeKey, $value) extends NodeVisitorAbstract {
24+
public function __construct(
25+
private readonly string $attributeKey,
26+
private readonly mixed $value
27+
) {
28+
}
29+
30+
public function enterNode(Node $node): ?int
31+
{
32+
// avoid nested functions or classes
33+
if ($node instanceof Class_ || $node instanceof FunctionLike) {
34+
return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
35+
}
36+
37+
$node->setAttribute($this->attributeKey, $this->value);
38+
return null;
39+
}
40+
};
41+
42+
$nodeTraverser = new NodeTraverser($callableNodeVisitor);
43+
44+
$nodes = $nodesOrNode instanceof Node ? [$nodesOrNode] : $nodesOrNode;
45+
$nodeTraverser->traverse($nodes);
46+
}
47+
}

src/PhpParser/NodeTraverser/SimpleTraverser.php

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)