Skip to content

Commit e093ed9

Browse files
authored
[code-quality] add with() + callback() support to TypeWillReturnCallableArrowFunctionRector (#535)
* add fixture to TypeWillReturnCallableArrowFunctionRector * add with() + callback() support to TypeWillReturnCallableArrowFunctionRector
1 parent 0eff2fa commit e093ed9

File tree

2 files changed

+69
-10
lines changed

2 files changed

+69
-10
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\TypeWillReturnCallableArrowFunctionRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\TypeWillReturnCallableArrowFunctionRector\Source\SomeMockedClass;
7+
8+
final class FillKnownParamType extends TestCase
9+
{
10+
public function test($value): void
11+
{
12+
$this->createMock(SomeMockedClass::class)
13+
->method('someMethod')
14+
->with($this->callback(fn ($name) => $value));
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\TypeWillReturnCallableArrowFunctionRector\Fixture;
23+
24+
use PHPUnit\Framework\TestCase;
25+
use Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\TypeWillReturnCallableArrowFunctionRector\Source\SomeMockedClass;
26+
27+
final class FillKnownParamType extends TestCase
28+
{
29+
public function test($value): void
30+
{
31+
$this->createMock(SomeMockedClass::class)
32+
->method('someMethod')
33+
->with($this->callback(fn (string $name): int => $value));
34+
}
35+
}
36+
37+
?>

rules/CodeQuality/Rector/Class_/TypeWillReturnCallableArrowFunctionRector.php

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,8 @@ public function refactor(Node $node): ?Class_
146146
return null;
147147
}
148148

149-
if (! $this->isName($node->name, self::WILL_RETURN_CALLBACK)) {
150-
return null;
151-
}
152-
153-
$innerArg = $node->getArgs()[0]
154-
->value;
155-
if (! $innerArg instanceof ArrowFunction && ! $innerArg instanceof Closure) {
149+
$innerClosure = $this->matchInnerClosure($node);
150+
if (! $innerClosure instanceof Node) {
156151
return null;
157152
}
158153

@@ -205,7 +200,7 @@ public function refactor(Node $node): ?Class_
205200
return null;
206201
}
207202

208-
foreach ($innerArg->params as $key => $param) {
203+
foreach ($innerClosure->params as $key => $param) {
209204
// avoid typing variadic parameters
210205
if ($param->variadic) {
211206
continue;
@@ -239,14 +234,14 @@ public function refactor(Node $node): ?Class_
239234
$hasChanged = true;
240235
}
241236

242-
if (! $innerArg->returnType instanceof Node) {
237+
if (! $innerClosure->returnType instanceof Node) {
243238
$returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
244239
$parameterTypesAndReturnType->getReturnType(),
245240
TypeKind::RETURN
246241
);
247242

248243
if ($returnTypeNode instanceof Node) {
249-
$innerArg->returnType = $returnTypeNode;
244+
$innerClosure->returnType = $returnTypeNode;
250245
$hasChanged = true;
251246
}
252247
}
@@ -259,6 +254,33 @@ public function refactor(Node $node): ?Class_
259254
return $node;
260255
}
261256

257+
public function matchInnerClosure(MethodCall $methodCall): null|ArrowFunction|Closure
258+
{
259+
if ($this->isName($methodCall->name, 'with')) {
260+
// special case for nested callback
261+
$withFirstArg = $methodCall->getArgs()[0];
262+
263+
if ($withFirstArg->value instanceof MethodCall) {
264+
$nestedMethodCall = $withFirstArg->value;
265+
if ($this->isName($nestedMethodCall->name, 'callback')) {
266+
$nestedArg = $nestedMethodCall->getArgs()[0];
267+
if ($nestedArg->value instanceof ArrowFunction || $nestedArg->value instanceof Closure) {
268+
return $nestedArg->value;
269+
}
270+
}
271+
}
272+
}
273+
274+
if ($this->isName($methodCall->name, self::WILL_RETURN_CALLBACK)) {
275+
$innerArg = $methodCall->getArgs()[0];
276+
if ($innerArg->value instanceof ArrowFunction || $innerArg->value instanceof Closure) {
277+
return $innerArg->value;
278+
}
279+
}
280+
281+
return null;
282+
}
283+
262284
/**
263285
* @param array<string, string> $propertyNameToMockedTypes
264286
*/

0 commit comments

Comments
 (0)