From 67521d11f36c8a34b0f928107c9b62f5d1bd6bec Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 9 Jan 2026 22:44:35 +0700 Subject: [PATCH 1/7] Fix slug same class name but different set --- src/RuleFilter/ValueObject/RuleMetadata.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/RuleFilter/ValueObject/RuleMetadata.php b/src/RuleFilter/ValueObject/RuleMetadata.php index c9cc7dfe8..2a46d9080 100644 --- a/src/RuleFilter/ValueObject/RuleMetadata.php +++ b/src/RuleFilter/ValueObject/RuleMetadata.php @@ -43,9 +43,23 @@ public function getRuleShortClass(): string public function getSlug(): string { // turn "SomeRector" to "some-rector" - return str($this->getRuleShortClass()) + $lastSlug = str($this->getRuleShortClass()) ->snake('-') ->toString(); + + $currentSet = current($this->sets); + + if ($currentSet === false) { + return $lastSlug; + } + + $slug = $currentSet->getSlug(); + if ($slug !== '') { + $slug .= '-'; + } + + $slug .= $lastSlug; + return $slug; } public function getDescription(): string From 8bb2b6eafe3a5189fb4bdc2e5322243a62104f4e Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 9 Jan 2026 15:45:30 +0000 Subject: [PATCH 2/7] [rector] Rector fixes --- src/RuleFilter/ValueObject/RuleMetadata.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/RuleFilter/ValueObject/RuleMetadata.php b/src/RuleFilter/ValueObject/RuleMetadata.php index 2a46d9080..ec94d8c93 100644 --- a/src/RuleFilter/ValueObject/RuleMetadata.php +++ b/src/RuleFilter/ValueObject/RuleMetadata.php @@ -57,9 +57,7 @@ public function getSlug(): string if ($slug !== '') { $slug .= '-'; } - - $slug .= $lastSlug; - return $slug; + return $slug . $lastSlug; } public function getDescription(): string From 2ff70da30a8109d8443748a44591beac90b2d6f2 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 9 Jan 2026 15:46:07 +0000 Subject: [PATCH 3/7] [rector] Rector fixes --- src/RuleFilter/ValueObject/RuleMetadata.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/RuleFilter/ValueObject/RuleMetadata.php b/src/RuleFilter/ValueObject/RuleMetadata.php index ec94d8c93..b711c397a 100644 --- a/src/RuleFilter/ValueObject/RuleMetadata.php +++ b/src/RuleFilter/ValueObject/RuleMetadata.php @@ -57,6 +57,7 @@ public function getSlug(): string if ($slug !== '') { $slug .= '-'; } + return $slug . $lastSlug; } From 906fd386d7c31c2bdba29b1b27e8c39d9331c71f Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 9 Jan 2026 22:54:52 +0700 Subject: [PATCH 4/7] Fix only add sets prefix when there is duplicated name --- src/FileSystem/RectorFinder.php | 26 +++++++++++++++++++-- src/RuleFilter/ValueObject/RuleMetadata.php | 7 +++++- tests/RuleFilter/RuleFilterTest.php | 6 +++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/FileSystem/RectorFinder.php b/src/FileSystem/RectorFinder.php index 5ddf4552f..b091972ec 100644 --- a/src/FileSystem/RectorFinder.php +++ b/src/FileSystem/RectorFinder.php @@ -140,7 +140,9 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr $ruleMetadatas = []; - foreach ($this->findRectorClasses($directories) as $rectorClass) { + $findRectorClasses = $this->findRectorClasses($directories); + + foreach ($findRectorClasses as $rectorClass) { $rectorReflectionClass = new ReflectionClass($rectorClass); if ($rectorReflectionClass->isAbstract()) { continue; @@ -187,10 +189,30 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr $ruleDefinition->getDescription(), $ruleDefinition->getCodeSamples(), $currentRuleSets, - (string) $rectorReflectionClass->getFileName() + (string) $rectorReflectionClass->getFileName(), + $this->isDuplicatedLastName($findRectorClasses, $rectorReflectionClass->getShortName()) ); } return $ruleMetadatas; } + + /** + * @param array> $findRectorClasses + */ + private function isDuplicatedLastName(array $findRectorClasses, string $lastName): bool + { + $count = 0; + foreach ($findRectorClasses as $rectorClass) { + if (\str_ends_with($rectorClass, '\\' . $lastName)) { + $count++; + + if ($count === 2) { + return true; + } + } + } + + return false; + } } diff --git a/src/RuleFilter/ValueObject/RuleMetadata.php b/src/RuleFilter/ValueObject/RuleMetadata.php index b711c397a..ec5ab6923 100644 --- a/src/RuleFilter/ValueObject/RuleMetadata.php +++ b/src/RuleFilter/ValueObject/RuleMetadata.php @@ -29,7 +29,8 @@ public function __construct( private readonly string $description, private array $codeSamples, private readonly array $sets, - private readonly string $rectorRuleFilePath + private readonly string $rectorRuleFilePath, + private readonly bool $sameNameInDifferntSet ) { Assert::isAOf($ruleClass, RectorInterface::class); Assert::allIsAOf($sets, RectorSet::class); @@ -47,6 +48,10 @@ public function getSlug(): string ->snake('-') ->toString(); + if ($this->sameNameInDifferntSet === false) { + return $lastSlug; + } + $currentSet = current($this->sets); if ($currentSet === false) { diff --git a/tests/RuleFilter/RuleFilterTest.php b/tests/RuleFilter/RuleFilterTest.php index 330fb028b..f66201e14 100644 --- a/tests/RuleFilter/RuleFilterTest.php +++ b/tests/RuleFilter/RuleFilterTest.php @@ -20,14 +20,16 @@ public function testFilterBySetGroup(): void 'Some description', [], [], - 'some-rector.php' + 'some-rector.php', + false ); $ruleMetadataCommunity = new RuleMetadata( MigrateToSimplifiedAttributeRector::class, 'Some description', [], [], - 'some-rector.php' + 'some-rector.php', + false, ); $ruleFilter = $this->make(RuleFilter::class); From b301bd5a21a8f0c64be115f17c47e9fbe313da68 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 9 Jan 2026 22:55:28 +0700 Subject: [PATCH 5/7] Fix only add sets prefix when there is duplicated name --- src/RuleFilter/ValueObject/RuleMetadata.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RuleFilter/ValueObject/RuleMetadata.php b/src/RuleFilter/ValueObject/RuleMetadata.php index ec5ab6923..edf3f5086 100644 --- a/src/RuleFilter/ValueObject/RuleMetadata.php +++ b/src/RuleFilter/ValueObject/RuleMetadata.php @@ -30,7 +30,7 @@ public function __construct( private array $codeSamples, private readonly array $sets, private readonly string $rectorRuleFilePath, - private readonly bool $sameNameInDifferntSet + private readonly bool $sameNameInDifferentSet ) { Assert::isAOf($ruleClass, RectorInterface::class); Assert::allIsAOf($sets, RectorSet::class); @@ -48,7 +48,7 @@ public function getSlug(): string ->snake('-') ->toString(); - if ($this->sameNameInDifferntSet === false) { + if ($this->sameNameInDifferentSet === false) { return $lastSlug; } From 16621a946954de9c8685b663ee56d0b7d45af070 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 9 Jan 2026 15:55:39 +0000 Subject: [PATCH 6/7] [rector] Rector fixes --- src/FileSystem/RectorFinder.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/FileSystem/RectorFinder.php b/src/FileSystem/RectorFinder.php index b091972ec..00f557510 100644 --- a/src/FileSystem/RectorFinder.php +++ b/src/FileSystem/RectorFinder.php @@ -142,8 +142,8 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr $findRectorClasses = $this->findRectorClasses($directories); - foreach ($findRectorClasses as $rectorClass) { - $rectorReflectionClass = new ReflectionClass($rectorClass); + foreach ($findRectorClasses as $findRectorClass) { + $rectorReflectionClass = new ReflectionClass($findRectorClass); if ($rectorReflectionClass->isAbstract()) { continue; } @@ -173,14 +173,14 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr throw new InvalidRuleDescriptionException( sprintf( 'Rule "%s" has invalid code samples:%s"%s"', - $rectorClass, + $findRectorClass, PHP_EOL . PHP_EOL, $throwable->getMessage() ) ); } - $ruleDefinition->setRuleClass($rectorClass); + $ruleDefinition->setRuleClass($findRectorClass); $currentRuleSets = $this->findRuleUsedSets($ruleDefinition, $rectorSets); @@ -203,9 +203,9 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr private function isDuplicatedLastName(array $findRectorClasses, string $lastName): bool { $count = 0; - foreach ($findRectorClasses as $rectorClass) { - if (\str_ends_with($rectorClass, '\\' . $lastName)) { - $count++; + foreach ($findRectorClasses as $findRectorClass) { + if (\str_ends_with($findRectorClass, '\\' . $lastName)) { + ++$count; if ($count === 2) { return true; From 1c16962c264ec4414d6a7a9cfc9c697b45731a91 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 9 Jan 2026 23:15:19 +0700 Subject: [PATCH 7/7] add test for duplicated short name to have set prefix on slug --- tests/FileSystem/RectorFinderTest.php | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tests/FileSystem/RectorFinderTest.php diff --git a/tests/FileSystem/RectorFinderTest.php b/tests/FileSystem/RectorFinderTest.php new file mode 100644 index 000000000..57a2aa694 --- /dev/null +++ b/tests/FileSystem/RectorFinderTest.php @@ -0,0 +1,66 @@ +rectorFinder = new RectorFinder(new RectorSetsTreeProvider()); + } + + public function testFindDuplicated(): void + { + $foundRectors = $this->rectorFinder->find(); + + $shortNames = []; + $longNames = []; + foreach ($foundRectors as $ruleMetadata) { + $shortNames[] = $ruleMetadata->getRuleShortClass(); + $longNames[] = $ruleMetadata->getRectorClass(); + } + + $uniqueShortNames = array_unique($shortNames); + $uniqueLongNames = array_unique($longNames); + + $this->assertNotSame( + count($uniqueShortNames), + count($uniqueLongNames), + 'There are duplicated short class names.' + ); + + // get duplicated short names and report different slug + $duplicatedShortNames = array_diff_key($shortNames, $uniqueShortNames); + + $this->assertContains( + 'DeprecatedAnnotationToDeprecatedAttributeRector', + $duplicatedShortNames, + 'Expected DeprecatedAnnotationToDeprecatedAttributeRector to be one of the duplicated short names.' + ); + + foreach ($foundRectors as $foundRector) { + if ($foundRector->getRectorClass() === DeprecatedAnnotationToDeprecatedAttributeRector::class) { + $this->assertSame( + 'php-php-84-deprecated-annotation-to-deprecated-attribute-rector', + $foundRector->getSlug() + ); + } + + if ($foundRector->getRectorClass() === \Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector::class) { + $this->assertSame( + 'php-php-85-deprecated-annotation-to-deprecated-attribute-rector', + $foundRector->getSlug() + ); + } + } + } +}