Skip to content

Commit a389320

Browse files
committed
Make PhpClassReflection::getProperty() always return PhpPropertyReflection
1 parent 774f1ab commit a389320

File tree

4 files changed

+56
-33
lines changed

4 files changed

+56
-33
lines changed

src/Reflection/Php/PhpClassReflectionExtension.php

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
use PHPStan\Reflection\Deprecation\DeprecationProvider;
2626
use PHPStan\Reflection\ExtendedFunctionVariant;
2727
use PHPStan\Reflection\ExtendedMethodReflection;
28-
use PHPStan\Reflection\ExtendedPropertyReflection;
2928
use PHPStan\Reflection\InitializerExprContext;
3029
use PHPStan\Reflection\MethodReflection;
3130
use PHPStan\Reflection\MethodsClassReflectionExtension;
@@ -69,7 +68,7 @@ final class PhpClassReflectionExtension
6968
implements PropertiesClassReflectionExtension, MethodsClassReflectionExtension
7069
{
7170

72-
/** @var ExtendedPropertyReflection[][] */
71+
/** @var PhpPropertyReflection[][] */
7372
private array $propertiesIncludingAnnotations = [];
7473

7574
/** @var PhpPropertyReflection[][] */
@@ -159,7 +158,7 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa
159158
return $classReflection->getNativeReflection()->hasProperty($propertyName);
160159
}
161160

162-
public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection
161+
public function getProperty(ClassReflection $classReflection, string $propertyName): PhpPropertyReflection
163162
{
164163
if (!isset($this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName])) {
165164
$this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName] = $this->createProperty($classReflection, $propertyName, true);
@@ -171,7 +170,6 @@ public function getProperty(ClassReflection $classReflection, string $propertyNa
171170
public function getNativeProperty(ClassReflection $classReflection, string $propertyName): PhpPropertyReflection
172171
{
173172
if (!isset($this->nativeProperties[$classReflection->getCacheKey()][$propertyName])) {
174-
/** @var PhpPropertyReflection $property */
175173
$property = $this->createProperty($classReflection, $propertyName, false);
176174
$this->nativeProperties[$classReflection->getCacheKey()][$propertyName] = $property;
177175
}
@@ -183,7 +181,7 @@ private function createProperty(
183181
ClassReflection $classReflection,
184182
string $propertyName,
185183
bool $includingAnnotations,
186-
): ExtendedPropertyReflection
184+
): PhpPropertyReflection
187185
{
188186
$propertyReflection = $classReflection->getNativeReflection()->getProperty($propertyName);
189187
$propertyName = $propertyReflection->getName();
@@ -230,31 +228,6 @@ private function createProperty(
230228
$isFinal = $classReflection->isFinal() || $propertyReflection->isFinal();
231229
$isAllowedPrivateMutation = false;
232230

233-
if (
234-
$includingAnnotations
235-
&& !$declaringClassReflection->isEnum()
236-
&& $this->annotationsPropertiesClassReflectionExtension->hasProperty($classReflection, $propertyName)
237-
) {
238-
$hierarchyDistances = $classReflection->getClassHierarchyDistances();
239-
$annotationProperty = $this->annotationsPropertiesClassReflectionExtension->getProperty($classReflection, $propertyName);
240-
if (!isset($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()])) {
241-
throw new ShouldNotHappenException();
242-
}
243-
244-
$distanceDeclaringClass = $propertyReflection->getDeclaringClass()->getName();
245-
$propertyTrait = $this->findPropertyTrait($propertyReflection);
246-
if ($propertyTrait !== null) {
247-
$distanceDeclaringClass = $propertyTrait;
248-
}
249-
if (!isset($hierarchyDistances[$distanceDeclaringClass])) {
250-
throw new ShouldNotHappenException();
251-
}
252-
253-
if ($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()] <= $hierarchyDistances[$distanceDeclaringClass]) {
254-
return $annotationProperty;
255-
}
256-
}
257-
258231
$docComment = $propertyReflection->getDocComment() !== false
259232
? $propertyReflection->getDocComment()
260233
: null;
@@ -423,6 +396,46 @@ private function createProperty(
423396
}
424397
}
425398

399+
if (
400+
$includingAnnotations
401+
&& !$declaringClassReflection->isEnum()
402+
&& $this->annotationsPropertiesClassReflectionExtension->hasProperty($classReflection, $propertyName)
403+
) {
404+
$hierarchyDistances = $classReflection->getClassHierarchyDistances();
405+
$annotationProperty = $this->annotationsPropertiesClassReflectionExtension->getProperty($classReflection, $propertyName);
406+
if (!isset($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()])) {
407+
throw new ShouldNotHappenException();
408+
}
409+
410+
$distanceDeclaringClass = $propertyReflection->getDeclaringClass()->getName();
411+
$propertyTrait = $this->findPropertyTrait($propertyReflection);
412+
if ($propertyTrait !== null) {
413+
$distanceDeclaringClass = $propertyTrait;
414+
}
415+
if (!isset($hierarchyDistances[$distanceDeclaringClass])) {
416+
throw new ShouldNotHappenException();
417+
}
418+
419+
if ($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()] <= $hierarchyDistances[$distanceDeclaringClass]) {
420+
return new PhpPropertyReflection(
421+
$annotationProperty->getDeclaringClass(),
422+
$declaringTrait,
423+
$nativeType,
424+
$annotationProperty->getPhpDocType(),
425+
$propertyReflection,
426+
$getHook,
427+
$setHook,
428+
$deprecatedDescription,
429+
$isDeprecated,
430+
$isInternal,
431+
$isReadOnlyByPhpDoc,
432+
$isAllowedPrivateMutation,
433+
$this->attributeReflectionFactory->fromNativeReflection($propertyReflection->getAttributes(), InitializerExprContext::fromClass($declaringClassReflection->getName(), $declaringClassReflection->getFileName())),
434+
$isFinal,
435+
);
436+
}
437+
}
438+
426439
return new PhpPropertyReflection(
427440
$declaringClassReflection,
428441
$declaringTrait,

tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1841,7 +1841,7 @@ public static function dataProperties(): array
18411841
'$this->overriddenReadOnlyProperty',
18421842
],
18431843
[
1844-
'string',
1844+
'DOMElement|null',
18451845
'$this->documentElement',
18461846
],
18471847
];

tests/PHPStan/Rules/Properties/AccessPropertiesInAssignRuleTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,12 @@ public function testObjectShapes(): void
130130

131131
public function testConflictingAnnotationProperty(): void
132132
{
133-
$this->analyse([__DIR__ . '/data/conflicting-annotation-property.php'], []);
133+
$this->analyse([__DIR__ . '/data/conflicting-annotation-property.php'], [
134+
[
135+
'Access to private property ConflictingAnnotationProperty\PropertyWithAnnotation::$test.',
136+
27,
137+
],
138+
]);
134139
}
135140

136141
public function testBug10477(): void

tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,12 @@ public function testConflictingAnnotationProperty(): void
947947
$this->checkThisOnly = false;
948948
$this->checkUnionTypes = true;
949949
$this->checkDynamicProperties = true;
950-
$this->analyse([__DIR__ . '/data/conflicting-annotation-property.php'], []);
950+
$this->analyse([__DIR__ . '/data/conflicting-annotation-property.php'], [
951+
[
952+
'Access to private property ConflictingAnnotationProperty\PropertyWithAnnotation::$test.',
953+
26,
954+
],
955+
]);
951956
}
952957

953958
#[RequiresPhp('>= 8.1')]

0 commit comments

Comments
 (0)