Skip to content

Commit a1789e8

Browse files
committed
wip
1 parent f8d993f commit a1789e8

File tree

5 files changed

+61
-45
lines changed

5 files changed

+61
-45
lines changed

rules/CodingStyle/Rector/Closure/StaticClosureRector.php

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
namespace Rector\CodingStyle\Rector\Closure;
66

77
use PhpParser\Node;
8-
use PhpParser\Node\Expr\CallLike;
98
use PhpParser\Node\Expr\Closure;
10-
use PhpParser\Node\Expr\FuncCall;
11-
use PhpParser\Node\Expr\MethodCall;
12-
use PhpParser\Node\Expr\StaticCall;
139
use Rector\CodingStyle\Guard\StaticGuard;
14-
use Rector\NodeAnalyzer\CallLikeExpectsThisBindedClosureArgsAnalyzer;
10+
use Rector\NodeTypeResolver\Node\AttributeKey;
11+
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\CallLikeThisBoundClosureArgsNodeVisitor;
1512
use Rector\Rector\AbstractRector;
1613
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1714
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@@ -21,11 +18,8 @@
2118
*/
2219
final class StaticClosureRector extends AbstractRector
2320
{
24-
private const CLOSURE_USES_THIS = 'has_this_closure';
25-
2621
public function __construct(
2722
private readonly StaticGuard $staticGuard,
28-
private readonly CallLikeExpectsThisBindedClosureArgsAnalyzer $callLikeExpectsThisBindedClosureArgsAnalyzer
2923
) {
3024
}
3125

@@ -67,47 +61,12 @@ public function getNodeTypes(): array
6761
return [Closure::class];
6862
}
6963

70-
public function beforeTraverse(array $nodes): array
71-
{
72-
parent::beforeTraverse($nodes);
73-
74-
$this->traverseNodesWithCallable($nodes, function (Node $node): ?CallLike {
75-
if (
76-
! $node instanceof MethodCall
77-
&& ! $node instanceof StaticCall
78-
&& ! $node instanceof FuncCall
79-
) {
80-
return null;
81-
}
82-
83-
if ($node->isFirstClassCallable()) {
84-
return null;
85-
}
86-
87-
$args = $this->callLikeExpectsThisBindedClosureArgsAnalyzer->getArgsUsingThisBindedClosure($node);
88-
89-
if ($args === []) {
90-
return null;
91-
}
92-
93-
foreach ($args as $arg) {
94-
if ($arg->value instanceof Closure && ! $arg->hasAttribute(self::CLOSURE_USES_THIS)) {
95-
$arg->value->setAttribute(self::CLOSURE_USES_THIS, true);
96-
}
97-
}
98-
99-
return $node;
100-
});
101-
102-
return $nodes;
103-
}
104-
10564
/**
10665
* @param Closure $node
10766
*/
10867
public function refactor(Node $node): ?Node
10968
{
110-
if ($node->hasAttribute(self::CLOSURE_USES_THIS)) {
69+
if ($node->hasAttribute(AttributeKey::CLOSURE_USES_THIS)) {
11170
return null;
11271
}
11372

src/DependencyInjection/LazyContainerFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor;
101101
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ByRefReturnNodeVisitor;
102102
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ByRefVariableNodeVisitor;
103+
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\CallLikeThisBoundClosureArgsNodeVisitor;
103104
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ClassConstFetchNodeVisitor;
104105
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\ContextNodeVisitor;
105106
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\GlobalVariableNodeVisitor;
@@ -252,6 +253,7 @@ final class LazyContainerFactory
252253
StaticVariableNodeVisitor::class,
253254
PropertyOrClassConstDefaultNodeVisitor::class,
254255
ClassConstFetchNodeVisitor::class,
256+
CallLikeThisBoundClosureArgsNodeVisitor::class,
255257
];
256258

257259
/**

src/NodeAnalyzer/CallLikeExpectsThisBindedClosureArgsAnalyzer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpParser\Node\Expr\CallLike;
99
use PhpParser\Node\Expr\Closure;
1010
use PHPStan\Reflection\ExtendedParameterReflection;
11+
use Rector\NodeTypeResolver\Node\AttributeKey;
1112
use Rector\NodeTypeResolver\PHPStan\ParametersAcceptorSelectorVariantsWrapper;
1213
use Rector\PHPStan\ScopeFetcher;
1314
use Rector\Reflection\ReflectionResolver;
@@ -35,7 +36,7 @@ public function getArgsUsingThisBindedClosure(CallLike $callLike): array
3536
return [];
3637
}
3738

38-
$scope = ScopeFetcher::fetch($callLike);
39+
$scope = $callLike->getAttribute(AttributeKey::SCOPE);
3940

4041
$parametersAcceptor = ParametersAcceptorSelectorVariantsWrapper::select($reflection, $callLike, $scope);
4142
$parameters = $parametersAcceptor->getParameters();

src/NodeTypeResolver/Node/AttributeKey.php

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

290290
public const PHP_VERSION_CONDITIONED = 'php_version_conditioned';
291+
292+
public const CLOSURE_USES_THIS = 'has_this_closure';
291293
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\Closure;
7+
use PhpParser\Node\Expr\FuncCall;
8+
use PhpParser\Node\Expr\MethodCall;
9+
use PhpParser\Node\Expr\StaticCall;
10+
use PhpParser\NodeVisitorAbstract;
11+
use PHPStan\Type\Type;
12+
use Rector\Contract\PhpParser\DecoratingNodeVisitorInterface;
13+
use Rector\NodeAnalyzer\CallLikeExpectsThisBindedClosureArgsAnalyzer;
14+
use Rector\NodeTypeResolver\Node\AttributeKey;
15+
16+
class CallLikeThisBoundClosureArgsNodeVisitor extends NodeVisitorAbstract implements DecoratingNodeVisitorInterface
17+
{
18+
public function __construct(
19+
private readonly CallLikeExpectsThisBindedClosureArgsAnalyzer $callLikeExpectsThisBindedClosureArgsAnalyzer
20+
)
21+
{
22+
}
23+
24+
public function enterNode(Node $node): ?Node
25+
{
26+
if (
27+
! $node instanceof MethodCall
28+
&& ! $node instanceof StaticCall
29+
&& ! $node instanceof FuncCall
30+
) {
31+
return null;
32+
}
33+
34+
if ($node->isFirstClassCallable()) {
35+
return null;
36+
}
37+
38+
$args = $this->callLikeExpectsThisBindedClosureArgsAnalyzer->getArgsUsingThisBindedClosure($node);
39+
40+
if ($args === []) {
41+
return null;
42+
}
43+
44+
foreach ($args as $arg) {
45+
if ($arg->value instanceof Closure && ! $arg->hasAttribute(AttributeKey::CLOSURE_USES_THIS)) {
46+
$arg->value->setAttribute(AttributeKey::CLOSURE_USES_THIS, true);
47+
}
48+
}
49+
50+
return $node;
51+
}
52+
}

0 commit comments

Comments
 (0)