Skip to content

Commit b2b18ab

Browse files
authored
Tidy up (#6259)
* cs * improve doc * cleanup
1 parent dc3850f commit b2b18ab

File tree

3 files changed

+70
-70
lines changed

3 files changed

+70
-70
lines changed

rector.php

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

33
declare(strict_types=1);
44

5-
use Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector;
65
use Rector\CodingStyle\Rector\String_\UseClassKeywordForClassNameResolutionRector;
76
use Rector\Config\RectorConfig;
87
use Rector\DeadCode\Rector\ConstFetch\RemovePhpVersionIdCheckRector;
98
use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector;
109
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
10+
use Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector;
1111

1212
return RectorConfig::configure()
1313
->withPreparedSets(

rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.php

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@
66

77
use PhpParser\Node;
88
use PhpParser\Node\Arg;
9+
use PhpParser\Node\Expr;
910
use PhpParser\Node\Expr\ArrowFunction;
1011
use PhpParser\Node\Expr\Closure;
1112
use PhpParser\Node\Expr\MethodCall;
1213
use PhpParser\Node\Expr\StaticCall;
1314
use PhpParser\Node\Identifier;
15+
use PhpParser\Node\Name;
1416
use PhpParser\Node\Param;
1517
use PHPStan\Reflection\ReflectionProvider;
1618
use PHPStan\Type\Constant\ConstantStringType;
1719
use PHPStan\Type\Generic\GenericClassStringType;
1820
use PHPStan\Type\ObjectType;
1921
use PHPStan\Type\StringType;
22+
use PHPStan\Type\Type;
2023
use Rector\Contract\Rector\ConfigurableRectorInterface;
2124
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
2225
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
@@ -37,8 +40,6 @@ final class AddClosureParamTypeFromArgRector extends AbstractRector implements C
3740
*/
3841
private array $addClosureParamTypeFromArgs = [];
3942

40-
private bool $hasChanged = false;
41-
4243
public function __construct(
4344
private readonly TypeComparator $typeComparator,
4445
private readonly StaticTypeMapper $staticTypeMapper,
@@ -48,17 +49,19 @@ public function __construct(
4849

4950
public function getRuleDefinition(): RuleDefinition
5051
{
51-
return new RuleDefinition('Add param types where needed', [
52+
return new RuleDefinition('Add closure param type based on known passed service/string types of method calls', [
5253
new ConfiguredCodeSample(
5354
<<<'CODE_SAMPLE'
55+
$app = new Container();
5456
$app->extend(SomeClass::class, function ($parameter) {});
5557
CODE_SAMPLE
5658
,
5759
<<<'CODE_SAMPLE'
60+
$app = new Container();
5861
$app->extend(SomeClass::class, function (SomeClass $parameter) {});
5962
CODE_SAMPLE
6063
,
61-
[new AddClosureParamTypeFromArg('SomeClass', 'extend', 1, 0, 0)]
64+
[new AddClosureParamTypeFromArg('Container', 'extend', 1, 0, 0)]
6265
),
6366
]);
6467
}
@@ -76,8 +79,6 @@ public function getNodeTypes(): array
7679
*/
7780
public function refactor(Node $node): ?Node
7881
{
79-
$this->hasChanged = false;
80-
8182
foreach ($this->addClosureParamTypeFromArgs as $addClosureParamTypeFromArg) {
8283
if ($node instanceof MethodCall) {
8384
$caller = $node->var;
@@ -87,26 +88,14 @@ public function refactor(Node $node): ?Node
8788
continue;
8889
}
8990

90-
if (! $this->isObjectType($caller, $addClosureParamTypeFromArg->getObjectType())) {
91-
continue;
92-
}
93-
94-
if (! $node->name instanceof Identifier) {
91+
if (! $this->isCallMatch($caller, $addClosureParamTypeFromArg, $node)) {
9592
continue;
9693
}
9794

98-
if (! $this->isName($node->name, $addClosureParamTypeFromArg->getMethodName())) {
99-
continue;
100-
}
101-
102-
$this->processCallLike($node, $addClosureParamTypeFromArg);
103-
}
104-
105-
if (! $this->hasChanged) {
106-
return null;
95+
return $this->processCallLike($node, $addClosureParamTypeFromArg);
10796
}
10897

109-
return $node;
98+
return null;
11099
}
111100

112101
/**
@@ -122,82 +111,96 @@ public function configure(array $configuration): void
122111
private function processCallLike(
123112
MethodCall|StaticCall $callLike,
124113
AddClosureParamTypeFromArg $addClosureParamTypeFromArg
125-
): void {
114+
): MethodCall|StaticCall|null {
126115
if ($callLike->isFirstClassCallable()) {
127-
return;
128-
}
129-
130-
if ($callLike->getArgs() === []) {
131-
return;
116+
return null;
132117
}
133118

134-
$arg = $callLike->args[$addClosureParamTypeFromArg->getCallLikePosition()] ?? null;
135-
if (! $arg instanceof Arg) {
136-
return;
119+
$callLikeArg = $callLike->args[$addClosureParamTypeFromArg->getCallLikePosition()] ?? null;
120+
if (! $callLikeArg instanceof Arg) {
121+
return null;
137122
}
138123

139124
// int positions shouldn't have names
140-
if ($arg->name instanceof Identifier) {
141-
return;
125+
if ($callLikeArg->name instanceof Identifier) {
126+
return null;
142127
}
143128

144-
$functionLike = $arg->value;
129+
$functionLike = $callLikeArg->value;
145130
if (! $functionLike instanceof Closure && ! $functionLike instanceof ArrowFunction) {
146-
return;
131+
return null;
147132
}
148133

149134
if (! isset($functionLike->params[$addClosureParamTypeFromArg->getFunctionLikePosition()])) {
150-
return;
135+
return null;
151136
}
152137

153-
if (! ($arg = $this->getArg(
154-
$addClosureParamTypeFromArg->getFromArgPosition(),
155-
$callLike->getArgs()
156-
)) instanceof Arg) {
157-
return;
138+
$callLikeArg = $callLike->getArgs()[$addClosureParamTypeFromArg->getFromArgPosition()] ?? null;
139+
if (! $callLikeArg instanceof Arg) {
140+
return null;
158141
}
159142

160-
$this->refactorParameter(
143+
$hasChanged = $this->refactorParameter(
161144
$functionLike->params[$addClosureParamTypeFromArg->getFunctionLikePosition()],
162-
$arg,
145+
$callLikeArg,
163146
);
164-
}
165147

166-
/**
167-
* @param Arg[] $args
168-
*/
169-
private function getArg(int $position, array $args): ?Arg
170-
{
171-
return $args[$position] ?? null;
148+
if ($hasChanged) {
149+
return $callLike;
150+
}
151+
152+
return null;
172153
}
173154

174-
private function refactorParameter(Param $param, Arg $arg): void
155+
private function refactorParameter(Param $param, Arg $arg): bool
175156
{
176-
$argType = $this->nodeTypeResolver->getType($arg->value);
177-
178-
if ($argType instanceof GenericClassStringType) {
179-
$closureType = $argType->getGenericType();
180-
} elseif ($argType instanceof ConstantStringType) {
181-
if ($this->reflectionProvider->hasClass($argType->getValue())) {
182-
$closureType = new ObjectType($argType->getValue());
183-
} else {
184-
$closureType = new StringType();
185-
}
186-
} else {
187-
return;
157+
$closureType = $this->resolveClosureType($arg->value);
158+
if (! $closureType instanceof Type) {
159+
return false;
188160
}
189161

190162
// already set → no change
191-
if ($param->type !== null) {
163+
if ($param->type instanceof Node) {
192164
$currentParamType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type);
193165
if ($this->typeComparator->areTypesEqual($currentParamType, $closureType)) {
194-
return;
166+
return false;
195167
}
196168
}
197169

198170
$paramTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($closureType, TypeKind::PARAM);
199-
$this->hasChanged = true;
200-
201171
$param->type = $paramTypeNode;
172+
173+
return true;
174+
}
175+
176+
private function isCallMatch(
177+
Name|Expr $caller,
178+
AddClosureParamTypeFromArg $addClosureParamTypeFromArg,
179+
StaticCall|MethodCall $call
180+
): bool {
181+
if (! $this->isObjectType($caller, $addClosureParamTypeFromArg->getObjectType())) {
182+
return false;
183+
}
184+
185+
return $this->isName($call->name, $addClosureParamTypeFromArg->getMethodName());
186+
}
187+
188+
private function resolveClosureType(Expr $expr): ?Type
189+
{
190+
$exprType = $this->nodeTypeResolver->getType($expr);
191+
192+
if ($exprType instanceof GenericClassStringType) {
193+
return $exprType->getGenericType();
194+
}
195+
196+
if ($exprType instanceof ConstantStringType) {
197+
if ($this->reflectionProvider->hasClass($exprType->getValue())) {
198+
return new ObjectType($exprType->getValue());
199+
}
200+
201+
return new StringType();
202+
}
203+
204+
return null;
202205
}
203206
}

rules/TypeDeclaration/ValueObject/AddClosureParamTypeFromArg.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
use PHPStan\Type\ObjectType;
88
use Rector\Validation\RectorAssert;
99

10-
/**
11-
* @see \Rector\Tests\TypeDeclaration\Rector\FunctionLike\AddClosureParamTypeFromArgRector\AddClosureParamTypeFromArgRectorTest
12-
*/
1310
final readonly class AddClosureParamTypeFromArg
1411
{
1512
/**

0 commit comments

Comments
 (0)