diff --git a/config/sets/phpunit-code-quality.php b/config/sets/phpunit-code-quality.php index 1be3f326..122b75bc 100644 --- a/config/sets/phpunit-code-quality.php +++ b/config/sets/phpunit-code-quality.php @@ -17,6 +17,7 @@ use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\BareCreateMockAssignToDirectUseRector; use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\DataProviderArrayItemsNewLinedRector; use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\EntityDocumentCreateMockToDirectNewRector; +use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\NoSetupWithParentCallOverrideRector; use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\RemoveEmptyTestMethodRector; use Rector\PHPUnit\CodeQuality\Rector\ClassMethod\ReplaceTestAnnotationWithPrefixedFunctionRector; use Rector\PHPUnit\CodeQuality\Rector\Expression\AssertArrayCastedObjectToAssertSameRector; @@ -134,5 +135,8 @@ EntityDocumentCreateMockToDirectNewRector::class, ReplaceAtMethodWithDesiredMatcherRector::class, BareCreateMockAssignToDirectUseRector::class, + + // readability + NoSetupWithParentCallOverrideRector::class, ]); }; diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/Fixture/keep_if_no_parent_call.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/Fixture/keep_if_no_parent_call.php.inc new file mode 100644 index 00000000..cf9f1037 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/Fixture/keep_if_no_parent_call.php.inc @@ -0,0 +1,14 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/NoSetupWithParentCallOverrideRectorTest.php b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/NoSetupWithParentCallOverrideRectorTest.php new file mode 100644 index 00000000..713534e7 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/NoSetupWithParentCallOverrideRectorTest.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/ClassMethod/NoSetupWithParentCallOverrideRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/config/configured_rule.php new file mode 100644 index 00000000..bee83355 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector/config/configured_rule.php @@ -0,0 +1,9 @@ +withRules([NoSetupWithParentCallOverrideRector::class]); diff --git a/rules/CodeQuality/NodeAnalyser/ParentCallDetector.php b/rules/CodeQuality/NodeAnalyser/ParentCallDetector.php new file mode 100644 index 00000000..3e4e1557 --- /dev/null +++ b/rules/CodeQuality/NodeAnalyser/ParentCallDetector.php @@ -0,0 +1,46 @@ +name->toString(); + + foreach ((array) $classMethod->stmts as $stmt) { + if (! $stmt instanceof Expression) { + continue; + } + + if (! $stmt->expr instanceof StaticCall) { + continue; + } + + $staticCall = $stmt->expr; + if (! $this->nodeNameResolver->isName($staticCall->class, 'parent')) { + continue; + } + + if (! $this->nodeNameResolver->isName($staticCall->name, $methodName)) { + continue; + } + + return true; + } + + return false; + } +} diff --git a/rules/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector.php b/rules/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector.php new file mode 100644 index 00000000..cfc0e27b --- /dev/null +++ b/rules/CodeQuality/Rector/ClassMethod/NoSetupWithParentCallOverrideRector.php @@ -0,0 +1,120 @@ +> + */ + public function getNodeTypes(): array + { + return [ClassMethod::class]; + } + + /** + * @param ClassMethod $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->testsNodeAnalyzer->isInTestClass($node)) { + return null; + } + + if (! $this->isName($node, 'setUp')) { + return null; + } + + if (! $this->parentCallDetector->hasParentCall($node)) { + return null; + } + + if (! $this->attributeFinder->hasAttributeByClasses($node, ['Override'])) { + return null; + } + + $hasChanged = false; + + foreach ($node->attrGroups as $attributeGroupKey => $attrGroup) { + foreach ($attrGroup->attrs as $attributeKey => $attribute) { + if (! $this->isName($attribute->name, 'Override')) { + continue; + } + + unset($attrGroup->attrs[$attributeKey]); + $hasChanged = true; + } + + if ($attrGroup->attrs === []) { + unset($node->attrGroups[$attributeGroupKey]); + } + } + + if (! $hasChanged) { + return null; + } + + return $node; + } +}