From 8b6ff2521fa445454a15cbd0589eaea70a2fee19 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 19 Dec 2024 14:11:43 +0800 Subject: [PATCH] Implement `EnumCaseNamingRule` --- src/Nexus/PHPStan/README.md | 1 + .../Rules/Enums/EnumCaseNamingRule.php | 48 +++++++++++++++++ src/Nexus/PHPStan/extension.neon | 1 + .../Rules/Enums/EnumCaseNamingRuleTest.php | 53 +++++++++++++++++++ .../Rules/Enums/data/enum-case-naming.php | 13 +++++ 5 files changed, 116 insertions(+) create mode 100644 src/Nexus/PHPStan/Rules/Enums/EnumCaseNamingRule.php create mode 100644 tests/PHPStan/Rules/Enums/EnumCaseNamingRuleTest.php create mode 100644 tests/PHPStan/Rules/Enums/data/enum-case-naming.php diff --git a/src/Nexus/PHPStan/README.md b/src/Nexus/PHPStan/README.md index a635a0d..5f5c0a5 100644 --- a/src/Nexus/PHPStan/README.md +++ b/src/Nexus/PHPStan/README.md @@ -32,6 +32,7 @@ The following rules will automatically be enabled once the `extension.neon` is a * Class properties - camelCase format with no underscores * Class methods - camelCase format with no underscores, except for magic methods where double underscores are allowed + * Enum cases - PascalCase format * Functions - lower_snake_case format 2. `@phpstan-`-prefixed PHPDoc tags should be avoided where possible: * `@phpstan-var` => `@var` diff --git a/src/Nexus/PHPStan/Rules/Enums/EnumCaseNamingRule.php b/src/Nexus/PHPStan/Rules/Enums/EnumCaseNamingRule.php new file mode 100644 index 0000000..6efa30e --- /dev/null +++ b/src/Nexus/PHPStan/Rules/Enums/EnumCaseNamingRule.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Nexus\PHPStan\Rules\Enums; + +use PhpParser\Node; +use PHPStan\Analyser\Scope; +use PHPStan\Rules\Rule; +use PHPStan\Rules\RuleErrorBuilder; + +/** + * @implements Rule + */ +final class EnumCaseNamingRule implements Rule +{ + public function getNodeType(): string + { + return Node\Stmt\EnumCase::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $enumCaseName = $node->name->name; + + if (preg_match('/(?:[A-Z][a-z]+)+/', $enumCaseName) !== 1) { + return [ + RuleErrorBuilder::message(\sprintf( + 'Enum case "%s" should be in PascalCase format.', + $enumCaseName, + )) + ->identifier('nexus.enumCaseNaming') + ->build(), + ]; + } + + return []; + } +} diff --git a/src/Nexus/PHPStan/extension.neon b/src/Nexus/PHPStan/extension.neon index 5114b0d..570374e 100644 --- a/src/Nexus/PHPStan/extension.neon +++ b/src/Nexus/PHPStan/extension.neon @@ -2,6 +2,7 @@ rules: - Nexus\PHPStan\Rules\CleanCode\AssignExprInCondRule - Nexus\PHPStan\Rules\CleanCode\DisallowedErrorSuppressionOperatorRule - Nexus\PHPStan\Rules\Constants\ClassConstantNamingRule + - Nexus\PHPStan\Rules\Enums\EnumCaseNamingRule - Nexus\PHPStan\Rules\Functions\FunctionNamingRule - Nexus\PHPStan\Rules\Methods\MethodNamingRule - Nexus\PHPStan\Rules\PhpDoc\DisallowedPhpstanDocTagRule diff --git a/tests/PHPStan/Rules/Enums/EnumCaseNamingRuleTest.php b/tests/PHPStan/Rules/Enums/EnumCaseNamingRuleTest.php new file mode 100644 index 0000000..e5e291f --- /dev/null +++ b/tests/PHPStan/Rules/Enums/EnumCaseNamingRuleTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Nexus\Tests\PHPStan\Rules\Enums; + +use Nexus\PHPStan\Rules\Enums\EnumCaseNamingRule; +use PHPStan\Rules\Rule; +use PHPStan\Testing\RuleTestCase; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; + +/** + * @internal + * + * @extends RuleTestCase + */ +#[CoversClass(EnumCaseNamingRule::class)] +#[Group('unit-test')] +final class EnumCaseNamingRuleTest extends RuleTestCase +{ + public function testRule(): void + { + $this->analyse([__DIR__.'/data/enum-case-naming.php'], [ + [ + 'Enum case "HEARTSSUIT" should be in PascalCase format.', + 10, + ], + [ + 'Enum case "diamonds_suit" should be in PascalCase format.', + 11, + ], + [ + 'Enum case "clubs_SUIT" should be in PascalCase format.', + 12, + ], + ]); + } + + protected function getRule(): Rule + { + return new EnumCaseNamingRule(); + } +} diff --git a/tests/PHPStan/Rules/Enums/data/enum-case-naming.php b/tests/PHPStan/Rules/Enums/data/enum-case-naming.php new file mode 100644 index 0000000..cf5f9c6 --- /dev/null +++ b/tests/PHPStan/Rules/Enums/data/enum-case-naming.php @@ -0,0 +1,13 @@ +