From a4b6070c6942dcf84349cd8fa1410d1070fcfdb0 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Wed, 5 Feb 2025 20:25:20 +0100 Subject: [PATCH 1/3] Add handling an attempt to declare a hooked property static --- Makefile | 1 + src/Rules/Properties/PropertyInClassRule.php | 11 +++++++++++ .../Properties/PropertyInClassRuleTest.php | 18 ++++++++++++++++++ .../data/static-hooked-properties.php | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/PHPStan/Rules/Properties/data/static-hooked-properties.php diff --git a/Makefile b/Makefile index d1fd73e1dd..7084ae3460 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,7 @@ lint: --exclude tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php \ --exclude tests/PHPStan/Rules/Properties/data/readonly-property-hooks.php \ --exclude tests/PHPStan/Rules/Properties/data/readonly-property-hooks-in-interface.php \ + --exclude tests/PHPStan/Rules/Properties/data/static-hooked-properties.php \ --exclude tests/PHPStan/Rules/Properties/data/virtual-hooked-properties.php \ --exclude tests/PHPStan/Rules/Classes/data/bug-12281.php \ --exclude tests/PHPStan/Rules/Traits/data/bug-12281.php \ diff --git a/src/Rules/Properties/PropertyInClassRule.php b/src/Rules/Properties/PropertyInClassRule.php index 661fb52c4c..bd7e495ab2 100644 --- a/src/Rules/Properties/PropertyInClassRule.php +++ b/src/Rules/Properties/PropertyInClassRule.php @@ -92,6 +92,17 @@ public function processNode(Node $node, Scope $scope): array } } + if ($node->isStatic()) { + if ($node->hasHooks()) { + return [ + RuleErrorBuilder::message('Hooked properties cannot be static.') + ->nonIgnorable() + ->identifier('property.hookStatic') + ->build(), + ]; + } + } + if ($node->isVirtual()) { if ($node->getDefault() !== null) { return [ diff --git a/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php b/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php index 6918499f75..54e041e694 100644 --- a/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php @@ -195,4 +195,22 @@ public function testPhp84AndVirtualHookedProperties(): void ]); } + public function testPhp84AndStaticHookedProperties(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/static-hooked-properties.php'], [ + [ + 'Hooked properties cannot be static.', + 7, + ], + [ + 'Hooked properties cannot be static.', + 15, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Properties/data/static-hooked-properties.php b/tests/PHPStan/Rules/Properties/data/static-hooked-properties.php new file mode 100644 index 0000000000..101f4b3b28 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/static-hooked-properties.php @@ -0,0 +1,18 @@ + $this->foo; + set => $this->foo = $value; + } +} + +abstract class HiWorld +{ + public static string $foo { + get => 'dummy'; + } +} From 376d521c151de7473d7e3e7f5f10fb5115f0c363 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Fri, 7 Feb 2025 19:44:26 +0100 Subject: [PATCH 2/3] Add handling an attempt to declare a hooked property static in an interface --- Makefile | 1 + .../Properties/PropertiesInInterfaceRule.php | 9 ++++++++ src/Rules/Properties/PropertyInClassRule.php | 2 +- .../PropertiesInInterfaceRuleTest.php | 22 +++++++++++++++++++ .../static-hooked-property-in-interface.php | 12 ++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Rules/Properties/data/static-hooked-property-in-interface.php diff --git a/Makefile b/Makefile index 7084ae3460..47ccd330d4 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,7 @@ lint: --exclude tests/PHPStan/Rules/Properties/data/readonly-property-hooks.php \ --exclude tests/PHPStan/Rules/Properties/data/readonly-property-hooks-in-interface.php \ --exclude tests/PHPStan/Rules/Properties/data/static-hooked-properties.php \ + --exclude tests/PHPStan/Rules/Properties/data/static-hooked-property-in-interface.php \ --exclude tests/PHPStan/Rules/Properties/data/virtual-hooked-properties.php \ --exclude tests/PHPStan/Rules/Classes/data/bug-12281.php \ --exclude tests/PHPStan/Rules/Traits/data/bug-12281.php \ diff --git a/src/Rules/Properties/PropertiesInInterfaceRule.php b/src/Rules/Properties/PropertiesInInterfaceRule.php index b6a3c7d493..db47bf23e4 100644 --- a/src/Rules/Properties/PropertiesInInterfaceRule.php +++ b/src/Rules/Properties/PropertiesInInterfaceRule.php @@ -66,6 +66,15 @@ public function processNode(Node $node, Scope $scope): array ]; } + if ($node->isStatic()) { + return [ + RuleErrorBuilder::message('Hooked properties cannot be static.') + ->nonIgnorable() + ->identifier('property.hookedStaticInInterface') + ->build(), + ]; + } + if ($this->hasAnyHookBody($node)) { return [ RuleErrorBuilder::message('Interfaces cannot include property hooks with bodies.') diff --git a/src/Rules/Properties/PropertyInClassRule.php b/src/Rules/Properties/PropertyInClassRule.php index bd7e495ab2..f14c9730a0 100644 --- a/src/Rules/Properties/PropertyInClassRule.php +++ b/src/Rules/Properties/PropertyInClassRule.php @@ -97,7 +97,7 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message('Hooked properties cannot be static.') ->nonIgnorable() - ->identifier('property.hookStatic') + ->identifier('property.hookedStatic') ->build(), ]; } diff --git a/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php b/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php index dc011f8a82..3d6dffcb8c 100644 --- a/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php @@ -140,4 +140,26 @@ public function testPhp84AndReadonlyPropertyHooksInInterface(): void ]); } + public function testPhp84AndStaticHookedPropertyInInterface(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/static-hooked-property-in-interface.php'], [ + [ + 'Hooked properties cannot be static.', + 7, + ], + [ + 'Hooked properties cannot be static.', + 9, + ], + [ + 'Hooked properties cannot be static.', + 11, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Properties/data/static-hooked-property-in-interface.php b/tests/PHPStan/Rules/Properties/data/static-hooked-property-in-interface.php new file mode 100644 index 0000000000..66f45edf78 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/static-hooked-property-in-interface.php @@ -0,0 +1,12 @@ + Date: Tue, 11 Feb 2025 11:34:27 +0100 Subject: [PATCH 3/3] Update src/Rules/Properties/PropertiesInInterfaceRule.php --- src/Rules/Properties/PropertiesInInterfaceRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rules/Properties/PropertiesInInterfaceRule.php b/src/Rules/Properties/PropertiesInInterfaceRule.php index db47bf23e4..3ff9546d35 100644 --- a/src/Rules/Properties/PropertiesInInterfaceRule.php +++ b/src/Rules/Properties/PropertiesInInterfaceRule.php @@ -70,7 +70,7 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message('Hooked properties cannot be static.') ->nonIgnorable() - ->identifier('property.hookedStaticInInterface') + ->identifier('property.hookedStatic') ->build(), ]; }