Skip to content

Commit 404733e

Browse files
authored
[CodeQuality] Skip nested value compare in CallbackSingleAssertToSimplerRector (#718)
* [CodeQuality] Skip nested value compare in CallbackSingleAssertToSimplerRector * handle flipped param order, skip nested compare both orders
1 parent 9bd2807 commit 404733e

4 files changed

Lines changed: 123 additions & 2 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\CallbackSingleAssertToSimplerRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class FlippedParamOrder extends TestCase
8+
{
9+
public function test()
10+
{
11+
$builder = $this->getMockBuilder('AnyType')->getMock();
12+
13+
$builder->expects($this->exactly(2))
14+
->method('add')
15+
->with($this->callback(function ($type): bool {
16+
$this->assertSame($type, TextType::class);
17+
18+
return true;
19+
}));
20+
}
21+
}
22+
23+
?>
24+
-----
25+
<?php
26+
27+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\CallbackSingleAssertToSimplerRector\Fixture;
28+
29+
use PHPUnit\Framework\TestCase;
30+
31+
final class FlippedParamOrder extends TestCase
32+
{
33+
public function test()
34+
{
35+
$builder = $this->getMockBuilder('AnyType')->getMock();
36+
37+
$builder->expects($this->exactly(2))
38+
->method('add')
39+
->with($this->equalTo(TextType::class));
40+
}
41+
}
42+
43+
?>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\CallbackSingleAssertToSimplerRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class SkipNestedCompare extends TestCase
8+
{
9+
public function test()
10+
{
11+
$builder = $this->getMockBuilder('AnyType')->getMock();
12+
13+
$builder->expects($this->exactly(2))
14+
->method('add')
15+
->with($this->callback(function (array $args): bool {
16+
$this->assertSame($args['label'], 'Test Label');
17+
18+
return true;
19+
}));
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\CodeQuality\Rector\MethodCall\CallbackSingleAssertToSimplerRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
final class SkipNestedCompareExpectedLeft extends TestCase
8+
{
9+
public function test()
10+
{
11+
$builder = $this->getMockBuilder('AnyType')->getMock();
12+
13+
$builder->expects($this->exactly(2))
14+
->method('add')
15+
->with($this->callback(function (array $args): bool {
16+
$this->assertSame('Test Label', $args['label']);
17+
18+
return true;
19+
}));
20+
}
21+
}

‎rules/CodeQuality/Rector/MethodCall/CallbackSingleAssertToSimplerRector.php‎

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpParser\Node\Expr\Closure;
1010
use PhpParser\Node\Expr\ConstFetch;
1111
use PhpParser\Node\Expr\MethodCall;
12+
use PhpParser\Node\Expr\Variable;
1213
use PhpParser\Node\Stmt\Expression;
1314
use PhpParser\Node\Stmt\Return_;
1415
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
@@ -153,8 +154,43 @@ private function matchCallbackSoleAssertSameExpected(Expr $expr): ?Expr
153154
return null;
154155
}
155156

156-
return $firstStmtExpr->getArgs()[0]
157-
->value;
157+
$assertSameArgs = $firstStmtExpr->getArgs();
158+
if (count($assertSameArgs) !== 2) {
159+
return null;
160+
}
161+
162+
$firstValue = $assertSameArgs[0]->value;
163+
$secondValue = $assertSameArgs[1]->value;
164+
165+
// one side must be the whole closure parameter; the other side is the expected value
166+
// nested access (e.g. $args['label']) is skipped, as equalTo() matches the whole argument
167+
if ($this->isClosureSoleParam($innerClosure, $secondValue)) {
168+
return $firstValue;
169+
}
170+
171+
if ($this->isClosureSoleParam($innerClosure, $firstValue)) {
172+
return $secondValue;
173+
}
174+
175+
return null;
176+
}
177+
178+
private function isClosureSoleParam(Closure $closure, Expr $expr): bool
179+
{
180+
if (count($closure->params) !== 1) {
181+
return false;
182+
}
183+
184+
if (! $expr instanceof Variable) {
185+
return false;
186+
}
187+
188+
$soleParam = $closure->params[0];
189+
if (! $soleParam->var instanceof Variable) {
190+
return false;
191+
}
192+
193+
return $this->nodeComparator->areNodesEqual($soleParam->var, $expr);
158194
}
159195

160196
private function isTrueReturn(Return_ $return): bool

0 commit comments

Comments
 (0)