diff --git a/config/services/services.neon b/config/services/services.neon index 4bb56395..d78cfd1e 100644 --- a/config/services/services.neon +++ b/config/services/services.neon @@ -13,17 +13,14 @@ services: - Symplify\PHPStanRules\Composer\ClassNamespaceMatcher - Symplify\PHPStanRules\Composer\ComposerAutoloadResolver - Symplify\PHPStanRules\Composer\Psr4PathValidator - - Symplify\PHPStanRules\Enum\EnumConstantAnalyzer - Symplify\PHPStanRules\Formatter\RequiredWithMessageFormatter - Symplify\PHPStanRules\Location\DirectoryChecker - Symplify\PHPStanRules\Matcher\PositionMatcher - - Symplify\PHPStanRules\Matcher\SharedNamePrefixMatcher - Symplify\PHPStanRules\Naming\BoolishNameAnalyser - Symplify\PHPStanRules\Naming\ClassToSuffixResolver - Symplify\PHPStanRules\NodeAnalyzer\ArrayAnalyzer - Symplify\PHPStanRules\NodeAnalyzer\AttributeFinder - Symplify\PHPStanRules\NodeAnalyzer\CacheIfAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\ClassAnalyzer - Symplify\PHPStanRules\NodeAnalyzer\EnumAnalyzer - Symplify\PHPStanRules\NodeAnalyzer\IfElseBranchAnalyzer - Symplify\PHPStanRules\NodeAnalyzer\IfResemblingMatchAnalyzer diff --git a/docs/rules_overview.md b/docs/rules_overview.md index 0cd58f65..7924c07d 100644 --- a/docs/rules_overview.md +++ b/docs/rules_overview.md @@ -1,4 +1,4 @@ -# 78 Rules Overview +# 77 Rules Overview ## AnnotateRegexClassConstWithRegexLinkRule @@ -316,56 +316,6 @@ class SomeCommand extends Command
-## EmbeddedEnumClassConstSpotterRule - -Constants "%s" should be extract to standalone enum class - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\Enum\EmbeddedEnumClassConstSpotterRule`](../src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\Enum\EmbeddedEnumClassConstSpotterRule - tags: [phpstan.rules.rule] - arguments: - parentTypes: - - AbstractObject -``` - -↓ - -```php -class SomeProduct extends AbstractObject -{ - public const STATUS_ENABLED = 1; - - public const STATUS_DISABLED = 0; -} -``` - -:x: - -
- -```php -class SomeProduct extends AbstractObject -{ -} - -class SomeStatus -{ - public const ENABLED = 1; - - public const DISABLED = 0; -} -``` - -:+1: - -
- ## ExclusiveNamespaceRule Exclusive namespace can only contain classes of specific type, nothing else diff --git a/src/Enum/EnumConstantAnalyzer.php b/src/Enum/EnumConstantAnalyzer.php deleted file mode 100644 index fa74bdd6..00000000 --- a/src/Enum/EnumConstantAnalyzer.php +++ /dev/null @@ -1,36 +0,0 @@ -isNonEnumConstantName($prefix); - } - - private function isNonEnumConstantName(string $name): bool - { - // not enum, but rather validation limit - if (\str_starts_with($name, 'MIN_')) { - return true; - } - - if (\str_ends_with($name, '_MIN')) { - return true; - } - - if (\str_starts_with($name, 'MAX_')) { - return true; - } - - return \str_ends_with($name, '_MAX'); - } -} diff --git a/src/Matcher/SharedNamePrefixMatcher.php b/src/Matcher/SharedNamePrefixMatcher.php deleted file mode 100644 index f784b7ec..00000000 --- a/src/Matcher/SharedNamePrefixMatcher.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ - public function match(array $values): array - { - $groups = []; - - $valuesCount = \count($values); - - for ($i = 0; $i < $valuesCount; ++$i) { - for ($j = $i + 1; $j < $valuesCount; ++$j) { - $pos = $this->strcmppos($values[$i], $values[$j]); - $prefix = \substr($values[$i], 0, $pos + 1); - - // append to grouping for this prefix. include both strings - this - // gives duplicates which we'll merge later - $groups[$prefix][] = [$values[$i], $values[$j]]; - } - } - - $uniqueGroupsByPrefix = []; - foreach ($groups as $prefix => $group) { - // to remove duplicates introduced above - $uniqueGroups = \array_unique(Arrays::flatten($group)); - - $uniqueGroupsByPrefix[$prefix] = $uniqueGroups; - } - - return $uniqueGroupsByPrefix; - } - - private function strcmppos(string $left, string $right): int - { - if ($left === '') { - return -1; - } - - if ($right === '') { - return -1; - } - - $position = 0; - while ($left[$position] && $left[$position] === $right[$position]) { - ++$position; - } - - return $position - 1; - } -} diff --git a/src/NodeAnalyzer/ClassAnalyzer.php b/src/NodeAnalyzer/ClassAnalyzer.php deleted file mode 100644 index 97fd81c3..00000000 --- a/src/NodeAnalyzer/ClassAnalyzer.php +++ /dev/null @@ -1,25 +0,0 @@ -getConstants() as $classConst) { - $constConst = $classConst->consts[0]; - $constantNames[] = $constConst->name->toString(); - } - - return $constantNames; - } -} diff --git a/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php b/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php deleted file mode 100644 index 4ed844be..00000000 --- a/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php +++ /dev/null @@ -1,152 +0,0 @@ - $parentTypes - */ - public function __construct( - private readonly ClassAnalyzer $classAnalyzer, - private readonly SharedNamePrefixMatcher $sharedNamePrefixMatcher, - private readonly EnumConstantAnalyzer $enumConstantAnalyzer, - private readonly array $parentTypes - ) { - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->shouldSkip($node)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $constantNames = $this->classAnalyzer->resolveConstantNames($classLike); - - $groupedByPrefix = $this->sharedNamePrefixMatcher->match($constantNames); - - $enumConstantNamesGroup = []; - - foreach ($groupedByPrefix as $prefix => $constantNames) { - if (\count($constantNames) < 1) { - continue; - } - - if ($this->enumConstantAnalyzer->isNonEnumConstantPrefix($prefix)) { - continue; - } - - $enumConstantNamesGroup[] = $constantNames; - } - - return $this->createErrorMessages($enumConstantNamesGroup); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeProduct extends AbstractObject -{ - public const STATUS_ENABLED = 1; - - public const STATUS_DISABLED = 0; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeProduct extends AbstractObject -{ -} - -class SomeStatus -{ - public const ENABLED = 1; - - public const DISABLED = 0; -} -CODE_SAMPLE - , - [ - 'parentTypes' => ['AbstractObject'], - ] - )]); - } - - private function shouldSkip(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - - // already enum - if (\str_contains($classReflection->getName(), '\\Enum\\') && ! \str_contains( - $classReflection->getName(), - '\\Rules\\Enum\\' - )) { - return true; - } - - foreach ($this->parentTypes as $parentType) { - if ($classReflection->isSubclassOf($parentType)) { - return false; - } - } - - return true; - } - - /** - * @param string[][] $enumConstantNamesGroup - * @return string[] - */ - private function createErrorMessages(array $enumConstantNamesGroup): array - { - $errorMessages = []; - - foreach ($enumConstantNamesGroup as $enumConstantNameGroup) { - $enumConstantNamesString = \implode('", "', $enumConstantNameGroup); - $errorMessages[] = \sprintf(self::ERROR_MESSAGE, $enumConstantNamesString); - } - - return $errorMessages; - } -} diff --git a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php b/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php deleted file mode 100644 index 10f64e90..00000000 --- a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ -> $expectedErrorsWithLines - */ - #[DataProvider('provideData')] - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipVariousConstantName.php', []]; - yield [__DIR__ . '/Fixture/SkipMinMax.php', []]; - yield [__DIR__ . '/Fixture/SkipMinMaxMultiple.php', []]; - - $errorMessage = \sprintf(EmbeddedEnumClassConstSpotterRule::ERROR_MESSAGE, 'TYPE_ACTIVE", "TYPE_PASSIVE'); - yield [__DIR__ . '/Fixture/ClassWithEnums.php', [[$errorMessage, 9]]]; - - yield [__DIR__ . '/Fixture/MixOfMultipleClassWithEnums.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(EmbeddedEnumClassConstSpotterRule::class); - } -} diff --git a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php b/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php deleted file mode 100644 index 4442cf4a..00000000 --- a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php +++ /dev/null @@ -1,14 +0,0 @@ -