Skip to content

Commit e1d53b0

Browse files
authored
[internal] rename FirstClassCallableRector to ArrayToFirstClassCallableRector to make behavior explicit (#7736)
* rename FirstClassCallableRector to ArrayToFirstClassCallableRector to make feature explicit * [internal] move decorating node visitors to PhpParser/NodeVisitor, easier to find; extract attribute key from FunctionLikeToFirstClassCallableRector * cs
1 parent f632f73 commit e1d53b0

17 files changed

+102
-66
lines changed

rules/CodingStyle/Rector/FunctionLike/FunctionLikeToFirstClassCallableRector.php

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
use PhpParser\NodeVisitor;
2323
use PHPStan\Analyser\Scope;
2424
use PHPStan\Reflection\Annotations\AnnotationMethodReflection;
25-
use PHPStan\Reflection\Native\NativeFunctionReflection;
26-
use PHPStan\Reflection\ParametersAcceptorSelector;
27-
use PHPStan\Type\CallableType;
2825
use Rector\NodeTypeResolver\Node\AttributeKey;
2926
use Rector\PhpParser\AstResolver;
3027
use Rector\PHPStan\ScopeFetcher;
@@ -40,11 +37,6 @@
4037
*/
4138
final class FunctionLikeToFirstClassCallableRector extends AbstractRector implements MinPhpVersionInterface
4239
{
43-
/**
44-
* @var string
45-
*/
46-
private const HAS_CALLBACK_SIGNATURE_MULTI_PARAMS = 'has_callback_signature_multi_params';
47-
4840
public function __construct(
4941
private readonly AstResolver $astResolver,
5042
private readonly ReflectionResolver $reflectionResolver
@@ -72,44 +64,14 @@ function ($parameter) {
7264

7365
public function getNodeTypes(): array
7466
{
75-
return [CallLike::class, ArrowFunction::class, Closure::class];
67+
return [ArrowFunction::class, Closure::class];
7668
}
7769

7870
/**
79-
* @param CallLike|ArrowFunction|Closure $node
71+
* @param ArrowFunction|Closure $node
8072
*/
8173
public function refactor(Node $node): null|CallLike
8274
{
83-
if ($node instanceof CallLike) {
84-
if ($node->isFirstClassCallable()) {
85-
return null;
86-
}
87-
88-
$methodReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
89-
foreach ($node->getArgs() as $arg) {
90-
if (! $arg->value instanceof Closure && ! $arg->value instanceof ArrowFunction) {
91-
continue;
92-
}
93-
94-
if ($methodReflection instanceof NativeFunctionReflection) {
95-
$parametersAcceptors = ParametersAcceptorSelector::combineAcceptors(
96-
$methodReflection->getVariants()
97-
);
98-
foreach ($parametersAcceptors->getParameters() as $extendedParameterReflection) {
99-
if ($extendedParameterReflection->getType() instanceof CallableType && $extendedParameterReflection->getType()->isVariadic()) {
100-
$arg->value->setAttribute(self::HAS_CALLBACK_SIGNATURE_MULTI_PARAMS, true);
101-
}
102-
}
103-
104-
return null;
105-
}
106-
107-
$arg->value->setAttribute(self::HAS_CALLBACK_SIGNATURE_MULTI_PARAMS, true);
108-
}
109-
110-
return null;
111-
}
112-
11375
$callLike = $this->extractCallLike($node);
11476
if ($callLike === null) {
11577
return null;
@@ -169,7 +131,7 @@ private function shouldSkip(
169131
return true;
170132
}
171133

172-
if ($node->getAttribute(self::HAS_CALLBACK_SIGNATURE_MULTI_PARAMS) === true) {
134+
if ($node->getAttribute(AttributeKey::HAS_CLOSURE_WITH_VARIADIC_ARGS) === true) {
173135
return true;
174136
}
175137

src/DependencyInjection/LazyContainerFactory.php

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,6 @@
9696
use Rector\NodeTypeResolver\NodeTypeResolver\ScalarTypeResolver;
9797
use Rector\NodeTypeResolver\NodeTypeResolver\StaticCallMethodCallTypeResolver;
9898
use Rector\NodeTypeResolver\NodeTypeResolver\TraitTypeResolver;
99-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ArgNodeVisitor;
100-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor;
101-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ByRefReturnNodeVisitor;
102-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ByRefVariableNodeVisitor;
103-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ClassConstFetchNodeVisitor;
104-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ContextNodeVisitor;
105-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\GlobalVariableNodeVisitor;
106-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\NameNodeVisitor;
107-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\PhpVersionConditionNodeVisitor;
108-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\PropertyOrClassConstDefaultNodeVisitor;
109-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\StaticVariableNodeVisitor;
110-
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\SymfonyClosureNodeVisitor;
11199
use Rector\NodeTypeResolver\PHPStan\Scope\PHPStanNodeScopeResolver;
112100
use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider;
113101
use Rector\Php80\AttributeDecorator\DoctrineConverterAttributeDecorator;
@@ -128,6 +116,19 @@
128116
use Rector\PhpParser\Comparing\NodeComparator;
129117
use Rector\PhpParser\Node\NodeFactory;
130118
use Rector\PhpParser\NodeTraverser\RectorNodeTraverser;
119+
use Rector\PhpParser\NodeVisitor\ArgNodeVisitor;
120+
use Rector\PhpParser\NodeVisitor\AssignedToNodeVisitor;
121+
use Rector\PhpParser\NodeVisitor\ByRefReturnNodeVisitor;
122+
use Rector\PhpParser\NodeVisitor\ByRefVariableNodeVisitor;
123+
use Rector\PhpParser\NodeVisitor\ClassConstFetchNodeVisitor;
124+
use Rector\PhpParser\NodeVisitor\ClosureWithVariadicParametersNodeVisitor;
125+
use Rector\PhpParser\NodeVisitor\ContextNodeVisitor;
126+
use Rector\PhpParser\NodeVisitor\GlobalVariableNodeVisitor;
127+
use Rector\PhpParser\NodeVisitor\NameNodeVisitor;
128+
use Rector\PhpParser\NodeVisitor\PhpVersionConditionNodeVisitor;
129+
use Rector\PhpParser\NodeVisitor\PropertyOrClassConstDefaultNodeVisitor;
130+
use Rector\PhpParser\NodeVisitor\StaticVariableNodeVisitor;
131+
use Rector\PhpParser\NodeVisitor\SymfonyClosureNodeVisitor;
131132
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
132133
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
133134
use Rector\PHPStanStaticTypeMapper\TypeMapper\AccessoryLiteralStringTypeMapper;
@@ -241,6 +242,7 @@ final class LazyContainerFactory
241242
*/
242243
private const DECORATING_NODE_VISITOR_CLASSES = [
243244
ArgNodeVisitor::class,
245+
ClosureWithVariadicParametersNodeVisitor::class,
244246
PhpVersionConditionNodeVisitor::class,
245247
AssignedToNodeVisitor::class,
246248
SymfonyClosureNodeVisitor::class,

src/NodeTypeResolver/Node/AttributeKey.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,6 @@ final class AttributeKey
282282
public const CLASS_CONST_FETCH_NAME = 'class_const_fetch_name';
283283

284284
public const PHP_VERSION_CONDITIONED = 'php_version_conditioned';
285+
286+
public const HAS_CLOSURE_WITH_VARIADIC_ARGS = 'has_closure_with_variadic_args';
285287
}

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php renamed to src/PhpParser/NodeVisitor/ArgNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr\FuncCall;

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.php renamed to src/PhpParser/NodeVisitor/AssignedToNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\ArrayItem;

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.php renamed to src/PhpParser/NodeVisitor/ByRefReturnNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\FunctionLike;

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php renamed to src/PhpParser/NodeVisitor/ByRefVariableNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr;

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ClassConstFetchNodeVisitor.php renamed to src/PhpParser/NodeVisitor/ClassConstFetchNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\Expr\ClassConstFetch;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PhpParser\NodeVisitor;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\ArrowFunction;
9+
use PhpParser\Node\Expr\CallLike;
10+
use PhpParser\Node\Expr\Closure;
11+
use PhpParser\NodeVisitorAbstract;
12+
use PHPStan\Reflection\Native\NativeFunctionReflection;
13+
use PHPStan\Reflection\ParametersAcceptorSelector;
14+
use PHPStan\Type\CallableType;
15+
use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface;
16+
use Rector\NodeTypeResolver\Node\AttributeKey;
17+
use Rector\Reflection\ReflectionResolver;
18+
19+
/**
20+
* Decorate method call, function call or static call, that accepts closure that
21+
* requires multiple args (variadic) - to handle them later in specific rules.
22+
*/
23+
final class ClosureWithVariadicParametersNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
24+
{
25+
public function __construct(
26+
private readonly ReflectionResolver $reflectionResolver,
27+
) {
28+
}
29+
30+
public function enterNode(Node $node): ?Node
31+
{
32+
if (! $node instanceof CallLike) {
33+
return null;
34+
}
35+
36+
if ($node->isFirstClassCallable()) {
37+
return null;
38+
}
39+
40+
if ($node->getArgs() === []) {
41+
return null;
42+
}
43+
44+
$methodReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
45+
46+
foreach ($node->getArgs() as $arg) {
47+
if (! $arg->value instanceof Closure && ! $arg->value instanceof ArrowFunction) {
48+
continue;
49+
}
50+
51+
if ($methodReflection instanceof NativeFunctionReflection) {
52+
$parametersAcceptors = ParametersAcceptorSelector::combineAcceptors(
53+
$methodReflection->getVariants()
54+
);
55+
56+
foreach ($parametersAcceptors->getParameters() as $extendedParameterReflection) {
57+
if ($extendedParameterReflection->getType() instanceof CallableType && $extendedParameterReflection->getType() ->isVariadic()) {
58+
$arg->value->setAttribute(AttributeKey::HAS_CLOSURE_WITH_VARIADIC_ARGS, true);
59+
}
60+
}
61+
62+
return null;
63+
}
64+
65+
$arg->value->setAttribute(AttributeKey::HAS_CLOSURE_WITH_VARIADIC_ARGS, true);
66+
}
67+
68+
return null;
69+
}
70+
}

src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.php renamed to src/PhpParser/NodeVisitor/ContextNodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
5+
namespace Rector\PhpParser\NodeVisitor;
66

77
use PhpParser\Node;
88
use PhpParser\Node\Arg;

0 commit comments

Comments
 (0)