From f6eebc6be877d6b945234705622e99df876d860b Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sun, 1 Dec 2024 02:45:14 +0800 Subject: [PATCH] Introduce `ClassAsClassConstantRule` --- Makefile | 1 + conf/config.level0.neon | 1 + .../Constants/ClassAsClassConstantRule.php | 40 +++++++++++++++++++ .../ClassAsClassConstantRuleTest.php | 33 +++++++++++++++ .../data/class-as-class-constant.php | 17 ++++++++ 5 files changed, 92 insertions(+) create mode 100644 src/Rules/Constants/ClassAsClassConstantRule.php create mode 100644 tests/PHPStan/Rules/Constants/ClassAsClassConstantRuleTest.php create mode 100644 tests/PHPStan/Rules/Constants/data/class-as-class-constant.php diff --git a/Makefile b/Makefile index 3282ee2c4e..11807088ca 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,7 @@ lint: --exclude tests/PHPStan/Rules/Classes/data/first-class-instantiation-callable.php \ --exclude tests/PHPStan/Rules/Classes/data/instantiation-callable.php \ --exclude tests/PHPStan/Rules/Classes/data/bug-9402.php \ + --exclude tests/PHPStan/Rules/Constants/data/class-as-class-constant.php \ --exclude tests/PHPStan/Rules/Constants/data/value-assigned-to-class-constant-native-type.php \ --exclude tests/PHPStan/Rules/Constants/data/overriding-constant-native-types.php \ --exclude tests/PHPStan/Rules/Methods/data/bug-10043.php \ diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 1382d99ee1..15f1048b86 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -68,6 +68,7 @@ rules: - PHPStan\Rules\Classes\NonClassAttributeClassRule - PHPStan\Rules\Classes\ReadOnlyClassRule - PHPStan\Rules\Classes\TraitAttributeClassRule + - PHPStan\Rules\Constants\ClassAsClassConstantRule - PHPStan\Rules\Constants\DynamicClassConstantFetchRule - PHPStan\Rules\Constants\FinalConstantRule - PHPStan\Rules\Constants\NativeTypedClassConstantRule diff --git a/src/Rules/Constants/ClassAsClassConstantRule.php b/src/Rules/Constants/ClassAsClassConstantRule.php new file mode 100644 index 0000000000..b10d2d0080 --- /dev/null +++ b/src/Rules/Constants/ClassAsClassConstantRule.php @@ -0,0 +1,40 @@ + + */ +final class ClassAsClassConstantRule implements Rule +{ + + public function getNodeType(): string + { + return Node\Stmt\ClassConst::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + + foreach ($node->consts as $const) { + if ($const->name->toLowerString() !== 'class') { + continue; + } + + $errors[] = RuleErrorBuilder::message('A class constant must not be called \'class\'; it is reserved for class name fetching.') + ->line($const->getStartLine()) + ->identifier('classConstant.class') + ->nonIgnorable() + ->build(); + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Rules/Constants/ClassAsClassConstantRuleTest.php b/tests/PHPStan/Rules/Constants/ClassAsClassConstantRuleTest.php new file mode 100644 index 0000000000..1a8fda4bf6 --- /dev/null +++ b/tests/PHPStan/Rules/Constants/ClassAsClassConstantRuleTest.php @@ -0,0 +1,33 @@ + + */ +class ClassAsClassConstantRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new ClassAsClassConstantRule(); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/class-as-class-constant.php'], [ + [ + 'A class constant must not be called \'class\'; it is reserved for class name fetching.', + 9, + ], + [ + 'A class constant must not be called \'class\'; it is reserved for class name fetching.', + 16, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Constants/data/class-as-class-constant.php b/tests/PHPStan/Rules/Constants/data/class-as-class-constant.php new file mode 100644 index 0000000000..fdf86f77f1 --- /dev/null +++ b/tests/PHPStan/Rules/Constants/data/class-as-class-constant.php @@ -0,0 +1,17 @@ +