diff --git a/src/Rules/PHPUnit/AssertSameWithCountRule.php b/src/Rules/PHPUnit/AssertSameWithCountRule.php index 2a5a765..744641a 100644 --- a/src/Rules/PHPUnit/AssertSameWithCountRule.php +++ b/src/Rules/PHPUnit/AssertSameWithCountRule.php @@ -50,6 +50,17 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).') ->identifier('phpunit.assertCount') + ->fixNode($node, static function (CallLike $node) use ($scope) { + $newArgs = self::rewriteArgs($node->args, $scope); + if ($newArgs === null) { + return $node; + } + + $node->name = new Node\Identifier('assertCount'); + $node->args = $newArgs; + + return $node; + }) ->build(), ]; } @@ -58,6 +69,17 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).') ->identifier('phpunit.assertCount') + ->fixNode($node, static function (CallLike $node) use ($scope) { + $newArgs = self::rewriteArgs($node->args, $scope); + if ($newArgs === null) { + return $node; + } + + $node->name = new Node\Identifier('assertCount'); + $node->args = $newArgs; + + return $node; + }) ->build(), ]; } @@ -109,4 +131,36 @@ private static function isNormalCount(Node\Expr\FuncCall $countFuncCall, Type $c return $isNormalCount; } + /** + * @param array $args + * @return list + */ + private static function rewriteArgs(array $args, Scope $scope): ?array + { + $newArgs = []; + for ($i = 0; $i < count($args); $i++) { + + if ( + $args[$i] instanceof Node\Arg + && $args[$i]->value instanceof CallLike + ) { + $value = $args[$i]->value; + if (self::isCountFunctionCall($value, $scope)) { + if (count($value->getArgs()) !== 1) { + return null; + } + + $newArgs[] = new Node\Arg($value->getArgs()[0]->value); + continue; + } elseif (self::isCountableMethodCall($value, $scope)) { + $newArgs[] = new Node\Arg($value->var); + continue; + } + } + + $newArgs[] = $args[$i]; + } + return $newArgs; + } + } diff --git a/tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php b/tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php index dfb940c..c90b2d6 100644 --- a/tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php +++ b/tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php @@ -42,6 +42,11 @@ public function testRule(): void ]); } + public function testFix(): void + { + $this->fix(__DIR__ . '/data/assert-same-count-fixable.php', __DIR__ . '/data/assert-same-count-fixable.php.fixed'); + } + /** * @return string[] */ diff --git a/tests/Rules/PHPUnit/data/assert-same-count-fixable.php b/tests/Rules/PHPUnit/data/assert-same-count-fixable.php new file mode 100644 index 0000000..a15c16d --- /dev/null +++ b/tests/Rules/PHPUnit/data/assert-same-count-fixable.php @@ -0,0 +1,42 @@ +assertSame(5, count([1, 2, 3])); + } + + public function testAssertSameWithCountRecursive($x) + { + $this->assertSame(5, count([1, 2, 3, $x], COUNT_RECURSIVE)); + } + + public function testAssertSameWithCountMethodForCountableVariableIsNotOK() + { + $bar = new \ExampleTestCaseFix\Bar (); + + $this->assertSame(5, $bar->count()); + } + + public function testAssertSameWithCountMethodForCountablePropertyFetchIsNotOK() + { + $foo = new \stdClass(); + $foo->bar = new Bar (); + + $this->assertSame(5, $foo->bar->count()); + } + +} + +class Bar implements \Countable { + public function count(): int + { + return 1; + } +} diff --git a/tests/Rules/PHPUnit/data/assert-same-count-fixable.php.fixed b/tests/Rules/PHPUnit/data/assert-same-count-fixable.php.fixed new file mode 100644 index 0000000..c2e9f96 --- /dev/null +++ b/tests/Rules/PHPUnit/data/assert-same-count-fixable.php.fixed @@ -0,0 +1,42 @@ +assertCount(5, [1, 2, 3]); + } + + public function testAssertSameWithCountRecursive($x) + { + $this->assertSame(5, count([1, 2, 3, $x], COUNT_RECURSIVE)); + } + + public function testAssertSameWithCountMethodForCountableVariableIsNotOK() + { + $bar = new \ExampleTestCaseFix\Bar (); + + $this->assertCount(5, $bar); + } + + public function testAssertSameWithCountMethodForCountablePropertyFetchIsNotOK() + { + $foo = new \stdClass(); + $foo->bar = new Bar (); + + $this->assertCount(5, $foo->bar); + } + +} + +class Bar implements \Countable { + public function count(): int + { + return 1; + } +}