Skip to content

Commit 49c27d8

Browse files
committed
ReadWritePropertiesExtensions are part of ClassPropertiesNode
1 parent 59fb0a3 commit 49c27d8

12 files changed

+116
-79
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
use PHPStan\Reflection\ParametersAcceptorSelector;
112112
use PHPStan\Reflection\Php\PhpMethodReflection;
113113
use PHPStan\Reflection\ReflectionProvider;
114+
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
114115
use PHPStan\ShouldNotHappenException;
115116
use PHPStan\TrinaryLogic;
116117
use PHPStan\Type\Accessory\NonEmptyArrayType;
@@ -195,6 +196,7 @@ public function __construct(
195196
private FileHelper $fileHelper,
196197
private TypeSpecifier $typeSpecifier,
197198
private DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider,
199+
private ReadWritePropertiesExtensionProvider $readWritePropertiesExtensionProvider,
198200
private bool $polluteScopeWithLoopInitialAssignments,
199201
private bool $polluteScopeWithAlwaysIterableForeach,
200202
private array $earlyTerminatingMethodCalls,
@@ -639,7 +641,7 @@ private function processStmtNode(
639641
$this->processAttributeGroups($stmt->attrGroups, $classScope, $classStatementsGatherer);
640642

641643
$this->processStmtNodes($stmt, $stmt->stmts, $classScope, $classStatementsGatherer);
642-
$nodeCallback(new ClassPropertiesNode($stmt, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls()), $classScope);
644+
$nodeCallback(new ClassPropertiesNode($stmt, $this->readWritePropertiesExtensionProvider, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls()), $classScope);
643645
$nodeCallback(new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls()), $classScope);
644646
$nodeCallback(new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches()), $classScope);
645647
$classReflection->evictPrivateSymbols();

src/Node/ClassPropertiesNode.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPStan\Node\Property\PropertyWrite;
1717
use PHPStan\Reflection\MethodReflection;
1818
use PHPStan\Rules\Properties\ReadWritePropertiesExtension;
19+
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
1920
use PHPStan\ShouldNotHappenException;
2021
use PHPStan\Type\MixedType;
2122
use PHPStan\Type\ObjectType;
@@ -33,7 +34,13 @@ class ClassPropertiesNode extends NodeAbstract implements VirtualNode
3334
* @param array<int, PropertyRead|PropertyWrite> $propertyUsages
3435
* @param array<int, MethodCall> $methodCalls
3536
*/
36-
public function __construct(private ClassLike $class, private array $properties, private array $propertyUsages, private array $methodCalls)
37+
public function __construct(
38+
private ClassLike $class,
39+
private ReadWritePropertiesExtensionProvider $readWritePropertiesExtensionProvider,
40+
private array $properties,
41+
private array $propertyUsages,
42+
private array $methodCalls,
43+
)
3744
{
3845
parent::__construct($class->getAttributes());
3946
}
@@ -74,13 +81,13 @@ public function getSubNodeNames(): array
7481

7582
/**
7683
* @param string[] $constructors
77-
* @param ReadWritePropertiesExtension[] $extensions
84+
* @param ReadWritePropertiesExtension[]|null $extensions
7885
* @return array{array<string, ClassPropertyNode>, array<array{string, int, ClassPropertyNode}>, array<array{string, int, ClassPropertyNode}>}
7986
*/
8087
public function getUninitializedProperties(
8188
Scope $scope,
8289
array $constructors,
83-
array $extensions,
90+
?array $extensions = null,
8491
): array
8592
{
8693
if (!$this->getClass() instanceof Class_) {
@@ -105,6 +112,10 @@ public function getUninitializedProperties(
105112
$properties[$property->getName()] = $property;
106113
}
107114

115+
if ($extensions === null) {
116+
$extensions = $this->readWritePropertiesExtensionProvider->getExtensions();
117+
}
118+
108119
foreach (array_keys($properties) as $name) {
109120
foreach ($extensions as $extension) {
110121
if (!$classReflection->hasNativeProperty($name)) {

src/Rules/DeadCode/UnusedPrivatePropertyRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public function processNode(Node $node, Scope $scope): array
161161
}
162162
}
163163

164-
[$uninitializedProperties] = $node->getUninitializedProperties($scope, [], $this->extensionProvider->getExtensions());
164+
[$uninitializedProperties] = $node->getUninitializedProperties($scope, []);
165165

166166
$errors = [];
167167
foreach ($properties as $name => $data) {

src/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class MissingReadOnlyByPhpDocPropertyAssignRule implements Rule
1919

2020
public function __construct(
2121
private ConstructorsHelper $constructorsHelper,
22-
private ReadWritePropertiesExtensionProvider $extensionProvider,
2322
)
2423
{
2524
}
@@ -35,7 +34,7 @@ public function processNode(Node $node, Scope $scope): array
3534
throw new ShouldNotHappenException();
3635
}
3736
$classReflection = $scope->getClassReflection();
38-
[$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), $this->extensionProvider->getExtensions());
37+
[$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection));
3938

4039
$errors = [];
4140
foreach ($properties as $propertyName => $propertyNode) {

src/Rules/Properties/MissingReadOnlyPropertyAssignRule.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class MissingReadOnlyPropertyAssignRule implements Rule
1919

2020
public function __construct(
2121
private ConstructorsHelper $constructorsHelper,
22-
private ReadWritePropertiesExtensionProvider $extensionProvider,
2322
)
2423
{
2524
}
@@ -35,7 +34,7 @@ public function processNode(Node $node, Scope $scope): array
3534
throw new ShouldNotHappenException();
3635
}
3736
$classReflection = $scope->getClassReflection();
38-
[$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), $this->extensionProvider->getExtensions());
37+
[$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection));
3938

4039
$errors = [];
4140
foreach ($properties as $propertyName => $propertyNode) {

src/Rules/Properties/UninitializedPropertyRule.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class UninitializedPropertyRule implements Rule
1818
{
1919

2020
public function __construct(
21-
private ReadWritePropertiesExtensionProvider $extensionProvider,
2221
private ConstructorsHelper $constructorsHelper,
2322
)
2423
{
@@ -35,7 +34,7 @@ public function processNode(Node $node, Scope $scope): array
3534
throw new ShouldNotHappenException();
3635
}
3736
$classReflection = $scope->getClassReflection();
38-
[$properties, $prematureAccess] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection), $this->extensionProvider->getExtensions());
37+
[$properties, $prematureAccess] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection));
3938

4039
$errors = [];
4140
foreach ($properties as $propertyName => $propertyNode) {

src/Testing/RuleTestCase.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use PHPStan\PhpDoc\PhpDocInheritanceResolver;
2121
use PHPStan\PhpDoc\StubPhpDocProvider;
2222
use PHPStan\Reflection\InitializerExprTypeResolver;
23+
use PHPStan\Rules\Properties\DirectReadWritePropertiesExtensionProvider;
24+
use PHPStan\Rules\Properties\ReadWritePropertiesExtension;
2325
use PHPStan\Rules\Registry as RuleRegistry;
2426
use PHPStan\Rules\Rule;
2527
use PHPStan\Type\FileTypeMapper;
@@ -50,6 +52,14 @@ protected function getCollectors(): array
5052
return [];
5153
}
5254

55+
/**
56+
* @return ReadWritePropertiesExtension[]
57+
*/
58+
protected function getReadWritePropertiesExtensions(): array
59+
{
60+
return [];
61+
}
62+
5363
protected function getTypeSpecifier(): TypeSpecifier
5464
{
5565
return self::getContainer()->getService('typeSpecifier');
@@ -78,6 +88,7 @@ private function getAnalyser(): Analyser
7888
self::getContainer()->getByType(FileHelper::class),
7989
$typeSpecifier,
8090
self::getContainer()->getByType(DynamicThrowTypeExtensionProvider::class),
91+
new DirectReadWritePropertiesExtensionProvider($this->getReadWritePropertiesExtensions()),
8192
$this->shouldPolluteScopeWithLoopInitialAssignments(),
8293
$this->shouldPolluteScopeWithAlwaysIterableForeach(),
8394
[],

src/Testing/TypeInferenceTestCase.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPStan\PhpDoc\PhpDocInheritanceResolver;
1515
use PHPStan\PhpDoc\StubPhpDocProvider;
1616
use PHPStan\Reflection\InitializerExprTypeResolver;
17+
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
1718
use PHPStan\TrinaryLogic;
1819
use PHPStan\Type\FileTypeMapper;
1920
use PHPStan\Type\VerbosityLevel;
@@ -53,6 +54,7 @@ public function processFile(
5354
self::getContainer()->getByType(FileHelper::class),
5455
$typeSpecifier,
5556
self::getContainer()->getByType(DynamicThrowTypeExtensionProvider::class),
57+
self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class),
5658
true,
5759
true,
5860
$this->getEarlyTerminatingMethodCalls(),

tests/PHPStan/Analyser/AnalyserTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHPStan\PhpDoc\StubPhpDocProvider;
1818
use PHPStan\Reflection\InitializerExprTypeResolver;
1919
use PHPStan\Rules\AlwaysFailRule;
20+
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
2021
use PHPStan\Rules\Registry as RuleRegistry;
2122
use PHPStan\Testing\PHPStanTestCase;
2223
use PHPStan\Type\FileTypeMapper;
@@ -485,6 +486,7 @@ private function createAnalyser(bool $reportUnmatchedIgnoredErrors): Analyser
485486
$fileHelper,
486487
$typeSpecifier,
487488
self::getContainer()->getByType(DynamicThrowTypeExtensionProvider::class),
489+
self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class),
488490
false,
489491
true,
490492
[],

tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,37 @@ protected function getRule(): Rule
2121
new ConstructorsHelper([
2222
'MissingReadOnlyPropertyAssignPhpDoc\\TestCase::setUp',
2323
]),
24-
new DirectReadWritePropertiesExtensionProvider([
25-
new class() implements ReadWritePropertiesExtension {
24+
);
25+
}
26+
27+
protected function getReadWritePropertiesExtensions(): array
28+
{
29+
return [
30+
new class() implements ReadWritePropertiesExtension {
2631

27-
public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool
28-
{
29-
return $this->isEntityId($property, $propertyName);
30-
}
32+
public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool
33+
{
34+
return $this->isEntityId($property, $propertyName);
35+
}
3136

32-
public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool
33-
{
34-
return $this->isEntityId($property, $propertyName);
35-
}
37+
public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool
38+
{
39+
return $this->isEntityId($property, $propertyName);
40+
}
3641

37-
public function isInitialized(PropertyReflection $property, string $propertyName): bool
38-
{
39-
return $this->isEntityId($property, $propertyName);
40-
}
42+
public function isInitialized(PropertyReflection $property, string $propertyName): bool
43+
{
44+
return $this->isEntityId($property, $propertyName);
45+
}
4146

42-
private function isEntityId(PropertyReflection $property, string $propertyName): bool
43-
{
44-
return $property->getDeclaringClass()->getName() === 'MissingReadOnlyPropertyAssignPhpDoc\\Entity'
45-
&& in_array($propertyName, ['id'], true);
46-
}
47+
private function isEntityId(PropertyReflection $property, string $propertyName): bool
48+
{
49+
return $property->getDeclaringClass()->getName() === 'MissingReadOnlyPropertyAssignPhpDoc\\Entity'
50+
&& in_array($propertyName, ['id'], true);
51+
}
4752

48-
},
49-
]),
50-
);
53+
},
54+
];
5155
}
5256

5357
public function testRule(): void

0 commit comments

Comments
 (0)