Skip to content

Commit 281f25e

Browse files
committed
handle nested arrays as well
1 parent dd7c4bf commit 281f25e

File tree

6 files changed

+52
-5
lines changed

6 files changed

+52
-5
lines changed

rules-tests/Php81/Rector/Array_/FirstClassCallableRector/Fixture/skip_on_class_const.php.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ final class SkipOnClassConst
66
{
77
private const CLASS_CONST = [SkipOnClassConst::class, 'size'];
88

9+
private const CLASS_CONST_NESTED = [
10+
'hey' => [SkipOnClassConst::class, 'size']
11+
];
12+
913
public function size()
1014
{
1115
}

rules-tests/Php81/Rector/Array_/FirstClassCallableRector/Fixture/skip_on_property.php.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ final class SkipOnProperty
66
{
77
private $prop = [SkipOnProperty::class, 'size'];
88

9+
private $nestedProperty = [
10+
'some_callback' => [SkipOnProperty::class, 'size']
11+
];
12+
913
public function size()
1014
{
1115
}

rules/Php81/Rector/Array_/FirstClassCallableRector.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
3232

3333
/**
34+
* @see RFC https://wiki.php.net/rfc/first_class_callable_syntax
3435
* @see \Rector\Tests\Php81\Rector\Array_\FirstClassCallableRector\FirstClassCallableRectorTest
3536
*/
3637
final class FirstClassCallableRector extends AbstractRector implements MinPhpVersionInterface
@@ -45,7 +46,6 @@ public function __construct(
4546

4647
public function getRuleDefinition(): RuleDefinition
4748
{
48-
// see RFC https://wiki.php.net/rfc/first_class_callable_syntax
4949
return new RuleDefinition('Upgrade array callable to first class callable', [
5050
new CodeSample(
5151
<<<'CODE_SAMPLE'
@@ -114,7 +114,7 @@ public function refactor(Node $node): StaticCall|MethodCall|null|int
114114
return null;
115115
}
116116

117-
if ($node->getAttribute(AttributeKey::IS_DEFAULT_CLASS_CONST_VALUE)) {
117+
if ($node->getAttribute(AttributeKey::IS_CLASS_CONST_VALUE)) {
118118
return null;
119119
}
120120

src/NodeTypeResolver/Node/AttributeKey.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,5 +289,5 @@ final class AttributeKey
289289

290290
public const IS_DEFAULT_PROPERTY_VALUE = 'is_default_property_value';
291291

292-
public const IS_DEFAULT_CLASS_CONST_VALUE = 'is_default_class_const_value';
292+
public const IS_CLASS_CONST_VALUE = 'is_default_class_const_value';
293293
}

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

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

1516
final class PropertyOrClassConstDefaultNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
1617
{
@@ -23,13 +24,13 @@ public function enterNode(Node $node): ?Node
2324
continue;
2425
}
2526

26-
$default->setAttribute(AttributeKey::IS_DEFAULT_PROPERTY_VALUE, true);
27+
SimpleTraverser::decorateWithTrueAttribute($default, AttributeKey::IS_DEFAULT_PROPERTY_VALUE);
2728
}
2829
}
2930

3031
if ($node instanceof ClassConst) {
3132
foreach ($node->consts as $const) {
32-
$const->value->setAttribute(AttributeKey::IS_DEFAULT_CLASS_CONST_VALUE, true);
33+
SimpleTraverser::decorateWithTrueAttribute($const->value, AttributeKey::IS_CLASS_CONST_VALUE);
3334
}
3435
}
3536

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PhpParser\NodeTraverser;
6+
7+
use PhpParser\Node;
8+
use PhpParser\NodeTraverser;
9+
use PhpParser\NodeVisitorAbstract;
10+
use Rector\NodeTypeResolver\Node\AttributeKey;
11+
12+
final class SimpleTraverser
13+
{
14+
/**
15+
* @param Node[]|Node $nodesOrNode
16+
* @param AttributeKey::* $attributeKey
17+
*/
18+
public static function decorateWithTrueAttribute(array|Node $nodesOrNode, string $attributeKey): void
19+
{
20+
$callableNodeVisitor = new class($attributeKey) extends NodeVisitorAbstract {
21+
public function __construct(
22+
private readonly string $attributeKey
23+
) {
24+
}
25+
26+
public function enterNode(Node $node)
27+
{
28+
$node->setAttribute($this->attributeKey, true);
29+
return null;
30+
}
31+
};
32+
33+
$nodeTraverser = new NodeTraverser($callableNodeVisitor);
34+
35+
$nodes = $nodesOrNode instanceof Node ? [$nodesOrNode] : $nodesOrNode;
36+
$nodeTraverser->traverse($nodes);
37+
}
38+
}

0 commit comments

Comments
 (0)