diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorConfiguredTest.php b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorConfiguredTest.php deleted file mode 100644 index dc90ce10..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorConfiguredTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/ConfiguredFixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorTest.php b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorTest.php deleted file mode 100644 index 082a69b6..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/AddCoversClassAttributeRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/rule.php'; - } -} diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_functional_test.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_functional_test.php.inc deleted file mode 100644 index c02acaf2..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_functional_test.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_integration_test.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_integration_test.php.inc deleted file mode 100644 index a2175eaf..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/ConfiguredFixture/adds_covers_class_integration_test.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class.php.inc deleted file mode 100644 index db141e06..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class_testcase.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class_testcase.php.inc deleted file mode 100644 index 03813b8f..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/adds_covers_class_testcase.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_abstract_class.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_abstract_class.php.inc deleted file mode 100644 index 5e936917..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_abstract_class.php.inc +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_interfaces.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_interfaces.php.inc deleted file mode 100644 index 861f1cfd..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_interfaces.php.inc +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_traits.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_traits.php.inc deleted file mode 100644 index f192c318..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_traits.php.inc +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_class.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_class.php.inc deleted file mode 100644 index e831b758..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_class.php.inc +++ /dev/null @@ -1,25 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_function.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_function.php.inc deleted file mode 100644 index c445d20b..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_function.php.inc +++ /dev/null @@ -1,25 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_nothing.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_nothing.php.inc deleted file mode 100644 index a4463636..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_already_added_covers_nothing.php.inc +++ /dev/null @@ -1,25 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_can_not_find_source_class.php.inc b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_can_not_find_source_class.php.inc deleted file mode 100644 index 02856d24..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/Fixture/skips_when_can_not_find_source_class.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/configured_rule.php deleted file mode 100644 index ea5f3dd3..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/configured_rule.php +++ /dev/null @@ -1,13 +0,0 @@ -ruleWithConfiguration(AddCoversClassAttributeRector::class, [ - new TestClassSuffixesConfig(['Test', 'TestCase', 'FunctionalTest', 'IntegrationTest']), - ]); -}; diff --git a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/rule.php b/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/rule.php deleted file mode 100644 index 3dabd2d4..00000000 --- a/rules-tests/CodeQuality/Rector/Class_/AddCoversClassAttributeRector/config/rule.php +++ /dev/null @@ -1,10 +0,0 @@ -rule(AddCoversClassAttributeRector::class); -}; diff --git a/rules/CodeQuality/Rector/Class_/AddCoversClassAttributeRector.php b/rules/CodeQuality/Rector/Class_/AddCoversClassAttributeRector.php index 6023eee4..61a9d17a 100644 --- a/rules/CodeQuality/Rector/Class_/AddCoversClassAttributeRector.php +++ b/rules/CodeQuality/Rector/Class_/AddCoversClassAttributeRector.php @@ -5,43 +5,20 @@ namespace Rector\PHPUnit\CodeQuality\Rector\Class_; use PhpParser\Node; -use PhpParser\Node\AttributeGroup; use PhpParser\Node\Stmt\Class_; -use PHPStan\Reflection\ReflectionProvider; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; use Rector\Contract\Rector\ConfigurableRectorInterface; -use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; -use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory; -use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; +use Rector\Exception\ShouldNotHappenException; use Rector\PHPUnit\ValueObject\TestClassSuffixesConfig; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; -use Webmozart\Assert\Assert; -use function array_filter; -use function array_merge; -use function count; -use function explode; -use function implode; -use function in_array; -use function preg_replace; -use function strtolower; -use function trim; -final class AddCoversClassAttributeRector extends AbstractRector implements ConfigurableRectorInterface +/** + * @deprecated as very specific and assumes test + class colocation. Better use custom rule isntead. + */ +final class AddCoversClassAttributeRector extends AbstractRector implements ConfigurableRectorInterface, DeprecatedInterface { - /** - * @var string[] - */ - private array $testClassSuffixes = ['Test', 'TestCase']; - - public function __construct( - private readonly ReflectionProvider $reflectionProvider, - private readonly PhpAttributeGroupFactory $phpAttributeGroupFactory, - private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer, - private readonly TestsNodeAnalyzer $testsNodeAnalyzer - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -93,38 +70,10 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - $className = $this->getName($node); - - if ($className === null) { - return null; - } - - if (! $this->testsNodeAnalyzer->isInTestClass($node)) { - return null; - } - - if ( - $this->phpAttributeAnalyzer->hasPhpAttributes($node, [ - 'PHPUnit\\Framework\\Attributes\\CoversNothing', - 'PHPUnit\\Framework\\Attributes\\CoversClass', - 'PHPUnit\\Framework\\Attributes\\CoversFunction', - ]) - ) { - return null; - } - - $possibleTestClassNames = $this->resolveSourceClassNames($className); - $matchingTestClassName = $this->matchExistingClassName($possibleTestClassNames); - - if (! is_string($matchingTestClassName)) { - return null; - } - - $coversAttributeGroup = $this->createAttributeGroup('\\' . $matchingTestClassName); - - $node->attrGroups = array_merge($node->attrGroups, [$coversAttributeGroup]); - - return $node; + throw new ShouldNotHappenException(sprintf( + '"%s" rule is deprecated. As very opinionated and assumes test + class colocation. Better use custom rule instead.', + self::class + )); } /** @@ -132,81 +81,5 @@ public function refactor(Node $node): ?Node */ public function configure(array $configuration): void { - Assert::countBetween($configuration, 0, 1); - - if (isset($configuration[0])) { - Assert::isInstanceOf($configuration[0], TestClassSuffixesConfig::class); - $this->testClassSuffixes = $configuration[0]->getSuffixes(); - } - } - - /** - * @return string[] - */ - private function resolveSourceClassNames(string $className): array - { - $classNameParts = explode('\\', $className); - $partCount = count($classNameParts); - - // Sort suffixes by length (longest first) to ensure more specific patterns match first - $sortedSuffixes = $this->testClassSuffixes; - usort($sortedSuffixes, static fn (string $a, string $b): int => strlen($b) <=> strlen($a)); - - $patterns = []; - foreach ($sortedSuffixes as $sortedSuffix) { - $patterns[] = '#' . preg_quote($sortedSuffix, '#') . '$#'; - } - - $classNameParts[$partCount - 1] = preg_replace($patterns, '', $classNameParts[$partCount - 1]); - - $possibleTestClassNames = [implode('\\', $classNameParts)]; - - $partsWithoutTests = array_filter( - $classNameParts, - static fn (string|null $part): bool => $part === null - ? false - : ! in_array(strtolower($part), ['test', 'tests'], true) - ); - - $possibleTestClassNames[] = implode('\\', $partsWithoutTests); - - return $possibleTestClassNames; - } - - /** - * @param string[] $classNames - */ - private function matchExistingClassName(array $classNames): ?string - { - foreach ($classNames as $className) { - if (! $this->reflectionProvider->hasClass($className)) { - continue; - } - - $classReflection = $this->reflectionProvider->getClass($className); - if ($classReflection->isInterface()) { - continue; - } - - if ($classReflection->isTrait()) { - continue; - } - - if ($classReflection->isAbstract()) { - continue; - } - - return $className; - } - - return null; - } - - private function createAttributeGroup(string $annotationValue): AttributeGroup - { - $attributeClass = 'PHPUnit\\Framework\\Attributes\\CoversClass'; - $attributeValue = trim($annotationValue) . '::class'; - - return $this->phpAttributeGroupFactory->createFromClassWithItems($attributeClass, [$attributeValue]); } }