diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml
index e762bb2b4b4..9d90053bab7 100644
--- a/.github/workflows/code_analysis.yaml
+++ b/.github/workflows/code_analysis.yaml
@@ -44,8 +44,7 @@ jobs:
--skip-type="Rector\\NodeTypeResolver\\PHPStan\\Scope\\Contract\\NodeVisitor\\ScopeResolverNodeVisitorInterface" \
--skip-type="Rector\\BetterPhpDocParser\\Contract\\BasePhpDocNodeVisitorInterface" \
--skip-type="Rector\\BetterPhpDocParser\\Contract\\PhpDocParser\\PhpDocNodeDecoratorInterface" \
- --skip-type="Rector\\BetterPhpDocParser\\ValueObject\\Type\\FullyQualifiedIdentifierTypeNode" \
- --skip-type="Rector\\Contract\\Rector\\CollectorRectorInterface"
+ --skip-type="Rector\\BetterPhpDocParser\\ValueObject\\Type\\FullyQualifiedIdentifierTypeNode"
-
name: 'Compatible PHPStan versions'
diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md
index 40977587831..e90a4d280fd 100644
--- a/build/target-repository/docs/rector_rules_overview.md
+++ b/build/target-repository/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 355 Rules Overview
+# 354 Rules Overview
@@ -46,7 +46,7 @@
- [Php83](#php83) (3)
-- [Privatization](#privatization) (5)
+- [Privatization](#privatization) (4)
- [Removing](#removing) (5)
@@ -5136,6 +5136,8 @@ Decorate read-only property with `readonly` attribute
Refactor Spatie enum class to native Enum
+:wrench: **configure it!**
+
- class: [`Rector\Php81\Rector\Class_\SpatieEnumClassToEnumRector`](../rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php)
```diff
@@ -5304,25 +5306,6 @@ Combine separated host and port on `ldap_connect()` args
## Privatization
-### FinalizeClassesWithoutChildrenCollectorRector
-
-Finalize classes without children using collectors
-
-- class: [`Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenCollectorRector`](../rules/Privatization/Rector/Class_/FinalizeClassesWithoutChildrenCollectorRector.php)
-
-```diff
--class FirstClass extends SecondClass
-+final class FirstClass extends SecondClass
- {
- }
-
- class SecondClass
- {
- }
-```
-
-
-
### FinalizeClassesWithoutChildrenRector
Finalize every class that has no children
diff --git a/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/FixtureUpperCaseSnakeCase/enum_with_camel_case_names.php.inc b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/FixtureUpperCaseSnakeCase/enum_with_camel_case_names.php.inc
new file mode 100644
index 00000000000..4d0f4d06ff0
--- /dev/null
+++ b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/FixtureUpperCaseSnakeCase/enum_with_camel_case_names.php.inc
@@ -0,0 +1,33 @@
+
+-----
+
diff --git a/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/UpperCaseSnakeCaseTest.php b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/UpperCaseSnakeCaseTest.php
new file mode 100644
index 00000000000..5fb53a48397
--- /dev/null
+++ b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/UpperCaseSnakeCaseTest.php
@@ -0,0 +1,28 @@
+doTestFile($filePath);
+ }
+
+ public static function provideData(): Iterator
+ {
+ return self::yieldFilesFromDirectory(__DIR__ . '/FixtureUpperCaseSnakeCase');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule_uppercase_snake_case.php';
+ }
+}
diff --git a/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/config/configured_rule_uppercase_snake_case.php b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/config/configured_rule_uppercase_snake_case.php
new file mode 100644
index 00000000000..67341b53445
--- /dev/null
+++ b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/config/configured_rule_uppercase_snake_case.php
@@ -0,0 +1,12 @@
+ruleWithConfiguration(SpatieEnumClassToEnumRector::class, [
+ SpatieEnumClassToEnumRector::TO_UPPER_SNAKE_CASE => true,
+ ]);
+};
diff --git a/rules/Php81/NodeFactory/EnumFactory.php b/rules/Php81/NodeFactory/EnumFactory.php
index 70336a115a0..789991cbea5 100644
--- a/rules/Php81/NodeFactory/EnumFactory.php
+++ b/rules/Php81/NodeFactory/EnumFactory.php
@@ -36,6 +36,12 @@
*/
private const PASCAL_CASE_TO_UNDERSCORE_REGEX = '/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[^A-Z])(?=[A-Z])|(?<=[A-Za-z])(?=[^A-Za-z])/';
+ /**
+ * @var string
+ * @see https://regex101.com/r/FneU33/1
+ */
+ private const MULTI_UNDERSCORES_REGEX = '#_{2,}#';
+
public function __construct(
private NodeNameResolver $nodeNameResolver,
private PhpDocInfoFactory $phpDocInfoFactory,
@@ -142,6 +148,7 @@ private function createEnumCaseFromDocComment(
$enumName = strtoupper(
Strings::replace($nodeValue->methodName, self::PASCAL_CASE_TO_UNDERSCORE_REGEX, '_$0')
);
+ $enumName = Strings::replace($enumName, self::MULTI_UNDERSCORES_REGEX, '_');
} else {
$enumName = strtoupper($nodeValue->methodName);
}
diff --git a/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php b/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php
index 25f76d540b1..133a317315d 100644
--- a/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php
+++ b/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php
@@ -13,7 +13,7 @@
use Rector\Rector\AbstractRector;
use Rector\ValueObject\PhpVersionFeature;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
-use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
+use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
@@ -26,6 +26,11 @@ final class SpatieEnumClassToEnumRector extends AbstractRector implements MinPhp
{
private bool $toUpperSnakeCase = false;
+ /**
+ * @var string
+ */
+ public const TO_UPPER_SNAKE_CASE = 'toUpperSnakeCase';
+
public function __construct(
private readonly EnumFactory $enumFactory
) {
@@ -39,7 +44,7 @@ public function provideMinPhpVersion(): int
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Refactor Spatie enum class to native Enum', [
- new CodeSample(
+ new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
use \Spatie\Enum\Enum;
@@ -61,7 +66,10 @@ enum StatusEnum : string
case PUBLISHED = 'published';
case ARCHIVED = 'archived';
}
-CODE_SAMPLE
+CODE_SAMPLE,
+[
+ SpatieEnumClassToEnumRector::TO_UPPER_SNAKE_CASE => false,
+]
),
]);
}
@@ -91,6 +99,6 @@ public function refactor(Node $node): ?Enum_
*/
public function configure(array $configuration): void
{
- $this->toUpperSnakeCase = true === ($configuration['toUpperSnakeCase'] ?? false);
+ $this->toUpperSnakeCase = $configuration[self::TO_UPPER_SNAKE_CASE] ?? false;
}
}
diff --git a/src/Config/RectorConfig.php b/src/Config/RectorConfig.php
index 1100055d993..4e621e67160 100644
--- a/src/Config/RectorConfig.php
+++ b/src/Config/RectorConfig.php
@@ -9,7 +9,6 @@
use Rector\Caching\Contract\ValueObject\Storage\CacheStorageInterface;
use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider;
-use Rector\Contract\Rector\CollectorRectorInterface;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Contract\Rector\RectorInterface;
use Rector\DependencyInjection\Laravel\ContainerMemento;
@@ -187,10 +186,6 @@ public function rule(string $rectorClass): void
$this->singleton($rectorClass);
$this->tag($rectorClass, RectorInterface::class);
- if (is_a($rectorClass, CollectorRectorInterface::class, true)) {
- $this->tag($rectorClass, CollectorRectorInterface::class);
- }
-
// for cache invalidation in case of change
SimpleParameterProvider::addParameter(Option::REGISTERED_RECTOR_RULES, $rectorClass);
}
diff --git a/src/DependencyInjection/LazyContainerFactory.php b/src/DependencyInjection/LazyContainerFactory.php
index cce6269202d..6e33c906144 100644
--- a/src/DependencyInjection/LazyContainerFactory.php
+++ b/src/DependencyInjection/LazyContainerFactory.php
@@ -58,7 +58,6 @@
use Rector\Console\Style\RectorStyle;
use Rector\Console\Style\SymfonyStyleFactory;
use Rector\Contract\DependencyInjection\ResetableInterface;
-use Rector\Contract\Rector\CollectorRectorInterface;
use Rector\Contract\Rector\RectorInterface;
use Rector\NodeDecorator\CreatedByRuleDecorator;
use Rector\NodeNameResolver\Contract\NodeNameResolverInterface;
@@ -435,10 +434,6 @@ public function create(): RectorConfig
->needs('$rectors')
->giveTagged(RectorInterface::class);
- $rectorConfig->when(RectorNodeTraverser::class)
- ->needs('$collectorRectors')
- ->giveTagged(CollectorRectorInterface::class);
-
$rectorConfig->when(ConfigInitializer::class)
->needs('$rectors')
->giveTagged(RectorInterface::class);
diff --git a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php
index b498fcd869e..61a05242049 100644
--- a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php
+++ b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php
@@ -6,7 +6,6 @@
use PhpParser\Node;
use PhpParser\NodeTraverser;
-use Rector\Contract\Rector\CollectorRectorInterface;
use Rector\Contract\Rector\RectorInterface;
use Rector\VersionBonding\PhpVersionedFilter;
@@ -60,15 +59,7 @@ private function prepareNodeVisitors(): void
}
// filer out by version
- $activeRectors = $this->phpVersionedFilter->filter($this->rectors);
-
- $nonCollectorActiveRectors = array_filter(
- $activeRectors,
- static fn (RectorInterface $rector): bool => ! $rector instanceof CollectorRectorInterface
- );
-
- $this->visitors = [...$this->visitors, ...$nonCollectorActiveRectors];
-
+ $this->visitors = $this->phpVersionedFilter->filter($this->rectors);
$this->areNodeVisitorsPrepared = true;
}
}
diff --git a/src/Testing/PHPUnit/AbstractRectorTestCase.php b/src/Testing/PHPUnit/AbstractRectorTestCase.php
index 2d1f5fe6473..16eaa86d123 100644
--- a/src/Testing/PHPUnit/AbstractRectorTestCase.php
+++ b/src/Testing/PHPUnit/AbstractRectorTestCase.php
@@ -8,7 +8,6 @@
use Iterator;
use Nette\Utils\FileSystem;
use Nette\Utils\Strings;
-use PHPStan\Collectors\Collector;
use PHPUnit\Framework\ExpectationFailedException;
use Rector\Application\ApplicationFileProcessor;
use Rector\Autoloading\AdditionalAutoloader;
@@ -17,7 +16,6 @@
use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider;
use Rector\Contract\DependencyInjection\ResetableInterface;
-use Rector\Contract\Rector\CollectorRectorInterface;
use Rector\Contract\Rector\RectorInterface;
use Rector\DependencyInjection\Laravel\ContainerMemento;
use Rector\Exception\ShouldNotHappenException;
@@ -89,8 +87,6 @@ protected function setUp(): void
// this has to be always empty, so we can add new rules with their configuration
$this->assertEmpty($rectorConfig->tagged(RectorInterface::class));
- $this->assertEmpty($rectorConfig->tagged(CollectorRectorInterface::class));
- $this->assertEmpty($rectorConfig->tagged(Collector::class));
$this->bootFromConfigFiles([$configFile]);
@@ -174,8 +170,6 @@ protected function forgetRectorsRulesAndCollectors(): void
// 1. forget tagged services
ContainerMemento::forgetTag($rectorConfig, RectorInterface::class);
- ContainerMemento::forgetTag($rectorConfig, Collector::class);
- ContainerMemento::forgetTag($rectorConfig, CollectorRectorInterface::class);
// 2. remove after binding too, to avoid setting configuration over and over again
$privatesAccessor = new PrivatesAccessor();
diff --git a/stubs/PHPStan/Collectors/Collector.php b/stubs/PHPStan/Collectors/Collector.php
deleted file mode 100644
index 385cd0c6b45..00000000000
--- a/stubs/PHPStan/Collectors/Collector.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- */
-
- public function getNodeType() : string;
- /**
- * @phpstan-param TNodeType $node
- * @return TValue|null Collected data
- */
- public function processNode(Node $node, Scope $scope);
-}