Skip to content

Commit 83ab593

Browse files
committed
Make AssertSameWithCountRule auto-fixable
1 parent 2fe9fbe commit 83ab593

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

src/Rules/PHPUnit/AssertSameWithCountRule.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ public function processNode(Node $node, Scope $scope): array
5050
return [
5151
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).')
5252
->identifier('phpunit.assertCount')
53+
->fixNode($node, static function (CallLike $node) use ($scope) {
54+
$newArgs = self::rewriteArgs($node->args, $scope);
55+
if ($newArgs === null) {
56+
return $node;
57+
}
58+
59+
$node->name = new Node\Identifier('assertCount');
60+
$node->args = $newArgs;
61+
62+
return $node;
63+
})
5364
->build(),
5465
];
5566
}
@@ -58,6 +69,12 @@ public function processNode(Node $node, Scope $scope): array
5869
return [
5970
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).')
6071
->identifier('phpunit.assertCount')
72+
->fixNode($node, static function (CallLike $node) use ($scope) {
73+
$node->name = new Node\Identifier('assertCount');
74+
$node->args = self::rewriteArgs($node->args, $scope);
75+
76+
return $node;
77+
})
6178
->build(),
6279
];
6380
}
@@ -109,4 +126,36 @@ private static function isNormalCount(Node\Expr\FuncCall $countFuncCall, Type $c
109126
return $isNormalCount;
110127
}
111128

129+
/**
130+
* @param array<Node\Arg|Node\VariadicPlaceholder> $args
131+
* @return list<Node\Arg|Node\VariadicPlaceholder>
132+
*/
133+
private static function rewriteArgs(array $args, Scope $scope): ?array
134+
{
135+
$newArgs = [];
136+
for ($i = 0; $i < count($args); $i++) {
137+
138+
if (
139+
$args[$i] instanceof Node\Arg
140+
&& $args[$i]->value instanceof CallLike
141+
) {
142+
$value = $args[$i]->value;
143+
if (self::isCountFunctionCall($value, $scope)) {
144+
if (count($value->getArgs()) !== 1) {
145+
return null;
146+
}
147+
148+
$newArgs[] = new Node\Arg($value->getArgs()[0]->value);
149+
continue;
150+
} elseif (self::isCountableMethodCall($value, $scope)) {
151+
$newArgs[] = new Node\Arg($value->var);
152+
continue;
153+
}
154+
}
155+
156+
$newArgs[] = $args[$i];
157+
}
158+
return $newArgs;
159+
}
160+
112161
}

tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public function testRule(): void
4242
]);
4343
}
4444

45+
public function testFix(): void
46+
{
47+
$this->fix(__DIR__ . '/data/assert-same-count-fixable.php', __DIR__ . '/data/assert-same-count-fixable.php.fixed');
48+
}
49+
4550
/**
4651
* @return string[]
4752
*/
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace ExampleTestCaseFix;
4+
5+
use const COUNT_RECURSIVE;
6+
7+
class AssertSameWithCountTestCase extends \PHPUnit\Framework\TestCase
8+
{
9+
10+
public function testAssertSameWithCount()
11+
{
12+
$this->assertSame(5, count([1, 2, 3]));
13+
}
14+
15+
public function testAssertSameWithCountRecursive($x)
16+
{
17+
$this->assertSame(5, count([1, 2, 3, $x], COUNT_RECURSIVE));
18+
}
19+
20+
public function testAssertSameWithCountMethodForCountableVariableIsNotOK()
21+
{
22+
$bar = new \ExampleTestCaseFix\Bar ();
23+
24+
$this->assertSame(5, $bar->count());
25+
}
26+
27+
public function testAssertSameWithCountMethodForCountablePropertyFetchIsNotOK()
28+
{
29+
$foo = new \stdClass();
30+
$foo->bar = new Bar ();
31+
32+
$this->assertSame(5, $foo->bar->count());
33+
}
34+
35+
}
36+
37+
class Bar implements \Countable {
38+
public function count(): int
39+
{
40+
return 1;
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace ExampleTestCaseFix;
4+
5+
use const COUNT_RECURSIVE;
6+
7+
class AssertSameWithCountTestCase extends \PHPUnit\Framework\TestCase
8+
{
9+
10+
public function testAssertSameWithCount()
11+
{
12+
$this->assertCount(5, [1, 2, 3]);
13+
}
14+
15+
public function testAssertSameWithCountRecursive($x)
16+
{
17+
$this->assertSame(5, count([1, 2, 3, $x], COUNT_RECURSIVE));
18+
}
19+
20+
public function testAssertSameWithCountMethodForCountableVariableIsNotOK()
21+
{
22+
$bar = new \ExampleTestCaseFix\Bar ();
23+
24+
$this->assertCount(5, $bar);
25+
}
26+
27+
public function testAssertSameWithCountMethodForCountablePropertyFetchIsNotOK()
28+
{
29+
$foo = new \stdClass();
30+
$foo->bar = new Bar ();
31+
32+
$this->assertCount(5, $foo->bar);
33+
}
34+
35+
}
36+
37+
class Bar implements \Countable {
38+
public function count(): int
39+
{
40+
return 1;
41+
}
42+
}

0 commit comments

Comments
 (0)