From aa97cab5d10b9964709c6deb3417fabe528155a6 Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Sat, 28 May 2022 20:43:40 +0200 Subject: [PATCH] Use ReadWritePropertiesExtensions in `MissingReadOnlyPropertyAssignRule` --- ...singReadOnlyByPhpDocPropertyAssignRule.php | 3 +- .../MissingReadOnlyPropertyAssignRule.php | 3 +- ...ReadOnlyByPhpDocPropertyAssignRuleTest.php | 28 +++++++++++++++++++ .../MissingReadOnlyPropertyAssignRuleTest.php | 28 +++++++++++++++++++ ...issing-readonly-property-assign-phpdoc.php | 9 ++++++ .../data/missing-readonly-property-assign.php | 7 +++++ 6 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php b/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php index db533a378a8..2880e3205c9 100644 --- a/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php +++ b/src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php @@ -19,6 +19,7 @@ class MissingReadOnlyByPhpDocPropertyAssignRule implements Rule public function __construct( private ConstructorsHelper $constructorsHelper, + private ReadWritePropertiesExtensionProvider $extensionProvider, ) { } @@ -34,7 +35,7 @@ public function processNode(Node $node, Scope $scope): array throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); - [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), []); + [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), $this->extensionProvider->getExtensions()); $errors = []; foreach ($properties as $propertyName => $propertyNode) { diff --git a/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php b/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php index 4dd408a4db7..62fbc5b153d 100644 --- a/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php +++ b/src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php @@ -19,6 +19,7 @@ class MissingReadOnlyPropertyAssignRule implements Rule public function __construct( private ConstructorsHelper $constructorsHelper, + private ReadWritePropertiesExtensionProvider $extensionProvider, ) { } @@ -34,7 +35,7 @@ public function processNode(Node $node, Scope $scope): array throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); - [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), []); + [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), $this->extensionProvider->getExtensions()); $errors = []; foreach ($properties as $propertyName => $propertyNode) { diff --git a/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php b/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php index cdc681ca0e9..6f5dd01d770 100644 --- a/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php @@ -3,8 +3,10 @@ namespace PHPStan\Rules\Properties; use PHPStan\Reflection\ConstructorsHelper; +use PHPStan\Reflection\PropertyReflection; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use function in_array; use const PHP_VERSION_ID; /** @@ -19,6 +21,32 @@ protected function getRule(): Rule new ConstructorsHelper([ 'MissingReadOnlyPropertyAssignPhpDoc\\TestCase::setUp', ]), + new DirectReadWritePropertiesExtensionProvider([ + new class() implements ReadWritePropertiesExtension { + + public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + public function isInitialized(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + private function isEntityId(PropertyReflection $property, string $propertyName): bool + { + return $property->getDeclaringClass()->getName() === 'MissingReadOnlyPropertyAssignPhpDoc\\Entity' + && in_array($propertyName, ['id'], true); + } + + }, + ]), ); } diff --git a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php index 1700b2331a4..391afc01d1d 100644 --- a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php @@ -3,8 +3,10 @@ namespace PHPStan\Rules\Properties; use PHPStan\Reflection\ConstructorsHelper; +use PHPStan\Reflection\PropertyReflection; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use function in_array; use const PHP_VERSION_ID; /** @@ -19,6 +21,32 @@ protected function getRule(): Rule new ConstructorsHelper([ 'MissingReadOnlyPropertyAssign\\TestCase::setUp', ]), + new DirectReadWritePropertiesExtensionProvider([ + new class() implements ReadWritePropertiesExtension { + + public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + public function isInitialized(PropertyReflection $property, string $propertyName): bool + { + return $this->isEntityId($property, $propertyName); + } + + private function isEntityId(PropertyReflection $property, string $propertyName): bool + { + return $property->getDeclaringClass()->getName() === 'MissingReadOnlyPropertyAssign\\Entity' + && in_array($propertyName, ['id'], true); + } + + }, + ]), ); } diff --git a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign-phpdoc.php b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign-phpdoc.php index 0ad5b65bc72..9d881ba9637 100644 --- a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign-phpdoc.php +++ b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign-phpdoc.php @@ -196,3 +196,12 @@ public function __construct() } } + + +class Entity +{ + + /** @readonly */ + private int $id; // does not complain about being uninitialized because of a ReadWritePropertiesExtension + +} diff --git a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php index 3a83a1a57b1..8f642100fac 100644 --- a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php +++ b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php @@ -153,3 +153,10 @@ public function __construct( } } + +class Entity +{ + + private readonly int $id; // does not complain about being uninitialized because of a ReadWritePropertiesExtension + +}