diff --git a/config/sets/phpunit-code-quality.php b/config/sets/phpunit-code-quality.php index eb5608fe..cd9867de 100644 --- a/config/sets/phpunit-code-quality.php +++ b/config/sets/phpunit-code-quality.php @@ -13,6 +13,7 @@ use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\RemoveEmptyTestMethodRector; use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\ReplaceTestAnnotationWithPrefixedFunctionRector; use Rector\PHPUnit\CodeQuality\Rector\Foreach_\SimplifyForeachInstanceOfRector; +use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertClassNameComparisonToInstanceOfRector; use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertCompareOnCountableWithMethodToAssertCountRector; use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertCompareToSpecificMethodRector; use Rector\PHPUnit\CodeQuality\Rector\MethodCall\AssertComparisonToSpecificMethodRector; @@ -58,6 +59,7 @@ NarrowUnusedSetUpDefinedPropertyRector::class, // specific asserts + AssertClassNameComparisonToInstanceOfRector::class, AssertCompareOnCountableWithMethodToAssertCountRector::class, AssertCompareToSpecificMethodRector::class, AssertComparisonToSpecificMethodRector::class, diff --git a/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/AssertClassNameComparisonToInstanceOfRectorTest.php b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/AssertClassNameComparisonToInstanceOfRectorTest.php new file mode 100644 index 00000000..9118ece4 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/AssertClassNameComparisonToInstanceOfRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/get_class.php.inc b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/get_class.php.inc new file mode 100644 index 00000000..cca6ddb5 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/get_class.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/skip_first_param.inc b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/skip_first_param.inc new file mode 100644 index 00000000..da154735 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/Fixture/skip_first_param.inc @@ -0,0 +1,27 @@ +assertSame(get_class($something), 'stdClass'); + } +} + +?> + ----- +assertSame(get_class($something), 'stdClass'); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/config/configured_rule.php new file mode 100644 index 00000000..2e8676c8 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(AssertClassNameComparisonToInstanceOfRector::class); +}; diff --git a/rules/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector.php b/rules/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector.php new file mode 100644 index 00000000..2d4e5be3 --- /dev/null +++ b/rules/CodeQuality/Rector/MethodCall/AssertClassNameComparisonToInstanceOfRector.php @@ -0,0 +1,93 @@ +assertNotEquals(SomeInstance::class, get_class($value));', + '$this->assertNotInstanceOf(SomeInstance::class, $value);' + ), + ] + ); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [MethodCall::class, StaticCall::class]; + } + + /** + * @param MethodCall|StaticCall $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->testsNodeAnalyzer->isPHPUnitMethodCallNames( + $node, + ['assertSame', 'assertNotSame', 'assertEquals', 'assertNotEquals'] + )) { + return null; + } + + if ($node->isFirstClassCallable()) { + return null; + } + + // we need 2 args + if (! isset($node->args[1])) { + return null; + } + + $secondArgument = $node->getArgs()[1]; + $secondArgumentValue = $secondArgument->value; + + if ($secondArgumentValue instanceof FuncCall && $this->isName($secondArgumentValue->name, 'get_class')) { + $countArg = $secondArgumentValue->getArgs()[0]; + $assertArgs[1] = new Arg($countArg->value); + + $node->args = $assertArgs; + $this->renameMethod($node); + + return $node; + } + + return null; + } + + private function renameMethod(MethodCall|StaticCall $node): void + { + if ($this->isNames($node->name, ['assertSame', 'assertEquals'])) { + $node->name = new Identifier('assertInstanceOf'); + } elseif ($this->isNames($node->name, ['assertNotSame', 'assertNotEquals'])) { + $node->name = new Identifier('assertNotInstanceOf'); + } + } +}