Skip to content

Commit 8e15aad

Browse files
authored
[Unambiguous] Use separate service for collect method calls of fluents (#7631)
1 parent 65b80d6 commit 8e15aad

File tree

2 files changed

+68
-39
lines changed

2 files changed

+68
-39
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Unambiguous\NodeAnalyzer;
6+
7+
use PhpParser\Node\Expr\MethodCall;
8+
use PHPStan\Type\ObjectType;
9+
use Rector\NodeTypeResolver\NodeTypeResolver;
10+
11+
final readonly class FluentMethodCallsCollector
12+
{
13+
public function __construct(
14+
private NodeTypeResolver $nodeTypeResolver
15+
) {
16+
}
17+
18+
/**
19+
* @return MethodCall[]
20+
*/
21+
public function resolve(MethodCall $firstMethodCall): array
22+
{
23+
// must be nested method call, so we avoid only single one
24+
if (! $firstMethodCall->var instanceof MethodCall) {
25+
return [];
26+
}
27+
28+
/** @var MethodCall[] $methodCalls */
29+
$methodCalls = [];
30+
31+
$currentMethodCall = $firstMethodCall;
32+
$classNameObjectType = null;
33+
while ($currentMethodCall instanceof MethodCall) {
34+
if ($currentMethodCall->isFirstClassCallable()) {
35+
return [];
36+
}
37+
38+
// must be exactly one argument
39+
if (count($currentMethodCall->getArgs()) !== 1) {
40+
return [];
41+
}
42+
43+
$objectType = $this->nodeTypeResolver->getType($currentMethodCall->var);
44+
if (! $objectType instanceof ObjectType) {
45+
return [];
46+
}
47+
48+
if ($classNameObjectType === null) {
49+
$classNameObjectType = $objectType->getClassName();
50+
} elseif ($classNameObjectType !== $objectType->getClassName()) {
51+
return [];
52+
}
53+
54+
$methodCalls[] = $currentMethodCall;
55+
$currentMethodCall = $currentMethodCall->var;
56+
}
57+
58+
return $methodCalls;
59+
}
60+
}

rules/Unambiguous/Rector/Expression/FluentSettersToStandaloneCallMethodRector.php

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Rector\Naming\Naming\PropertyNaming;
2020
use Rector\NodeTypeResolver\Node\AttributeKey;
2121
use Rector\Rector\AbstractRector;
22+
use Rector\Unambiguous\NodeAnalyzer\FluentMethodCallsCollector;
2223
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2324
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2425

@@ -30,7 +31,8 @@
3031
final class FluentSettersToStandaloneCallMethodRector extends AbstractRector
3132
{
3233
public function __construct(
33-
private readonly PropertyNaming $propertyNaming
34+
private readonly PropertyNaming $propertyNaming,
35+
private readonly FluentMethodCallsCollector $fluentMethodCallsCollector
3436
) {
3537
}
3638

@@ -87,54 +89,21 @@ public function refactor(Node $node): ?array
8789
return null;
8890
}
8991

90-
$firstMethodCall = $node->expr;
91-
92-
// must be nested method call, so we avoid only single one
93-
if (! $firstMethodCall->var instanceof MethodCall) {
94-
return null;
95-
}
96-
97-
/** @var MethodCall[] $methodCalls */
98-
$methodCalls = [];
99-
100-
$currentMethodCall = $firstMethodCall;
101-
$classNameObjectType = null;
102-
while ($currentMethodCall instanceof MethodCall) {
103-
if ($currentMethodCall->isFirstClassCallable()) {
104-
return null;
105-
}
106-
107-
// must be exactly one argument
108-
if (count($currentMethodCall->getArgs()) !== 1) {
109-
return null;
110-
}
111-
112-
$objectType = $this->getType($currentMethodCall->var);
113-
if (! $objectType instanceof ObjectType) {
114-
return null;
115-
}
116-
117-
if ($classNameObjectType === null) {
118-
$classNameObjectType = $objectType->getClassName();
119-
} elseif ($classNameObjectType !== $objectType->getClassName()) {
120-
return null;
121-
}
122-
123-
$methodCalls[] = $currentMethodCall;
124-
$currentMethodCall = $currentMethodCall->var;
125-
}
92+
$methodCalls = $this->fluentMethodCallsCollector->resolve($node->expr);
12693

12794
// at least 2 method calls
12895
if (count($methodCalls) < 1) {
12996
return null;
13097
}
13198

132-
$rootExpr = $currentMethodCall;
99+
$lastMethodCall = end($methodCalls);
100+
$rootExpr = $lastMethodCall->var;
101+
133102
if (! $rootExpr instanceof New_) {
134103
return null;
135104
}
136105

137-
if ($this->shouldSkipForVendorOrInternal($firstMethodCall)) {
106+
if ($this->shouldSkipForVendorOrInternal($node->expr)) {
138107
return null;
139108
}
140109

0 commit comments

Comments
 (0)