Skip to content

Commit ad3f422

Browse files
Introduce new methods
1 parent 9bbcb70 commit ad3f422

20 files changed

+838
-6
lines changed

src/Analyser/MutatingScope.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6127,7 +6127,10 @@ private function methodCallReturnType(Type $typeWithMethod, string $methodName,
61276127
return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $methodCall);
61286128
}
61296129

6130-
/** @api */
6130+
/**
6131+
* @api
6132+
* @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead
6133+
*/
61316134
public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
61326135
{
61336136
if ($typeWithProperty instanceof UnionType) {
@@ -6140,6 +6143,32 @@ public function getPropertyReflection(Type $typeWithProperty, string $propertyNa
61406143
return $typeWithProperty->getProperty($propertyName, $this);
61416144
}
61426145

6146+
/** @api */
6147+
public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6148+
{
6149+
if ($typeWithProperty instanceof UnionType) {
6150+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasInstanceProperty($propertyName)->yes());
6151+
}
6152+
if (!$typeWithProperty->hasInstanceProperty($propertyName)->yes()) {
6153+
return null;
6154+
}
6155+
6156+
return $typeWithProperty->getInstanceProperty($propertyName, $this);
6157+
}
6158+
6159+
/** @api */
6160+
public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6161+
{
6162+
if ($typeWithProperty instanceof UnionType) {
6163+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasStaticProperty($propertyName)->yes());
6164+
}
6165+
if (!$typeWithProperty->hasStaticProperty($propertyName)->yes()) {
6166+
return null;
6167+
}
6168+
6169+
return $typeWithProperty->getStaticProperty($propertyName, $this);
6170+
}
6171+
61436172
/**
61446173
* @param PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch
61456174
*/

src/Analyser/Scope.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ public function getMaybeDefinedVariables(): array;
7575

7676
public function hasConstant(Name $name): bool;
7777

78+
/** @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead */
7879
public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection;
7980

81+
public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection;
82+
83+
public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection;
84+
8085
public function getMethodReflection(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection;
8186

8287
public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection;

src/Type/ClosureType.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,36 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
315315
return $this->objectType->getUnresolvedPropertyPrototype($propertyName, $scope);
316316
}
317317

318+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
319+
{
320+
return $this->objectType->hasInstanceProperty($propertyName);
321+
}
322+
323+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
324+
{
325+
return $this->objectType->getInstanceProperty($propertyName, $scope);
326+
}
327+
328+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
329+
{
330+
return $this->objectType->getUnresolvedInstancePropertyPrototype($propertyName, $scope);
331+
}
332+
333+
public function hasStaticProperty(string $propertyName): TrinaryLogic
334+
{
335+
return $this->objectType->hasStaticProperty($propertyName);
336+
}
337+
338+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
339+
{
340+
return $this->objectType->getStaticProperty($propertyName, $scope);
341+
}
342+
343+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
344+
{
345+
return $this->objectType->getUnresolvedStaticPropertyPrototype($propertyName, $scope);
346+
}
347+
318348
public function canCallMethods(): TrinaryLogic
319349
{
320350
return $this->objectType->canCallMethods();

src/Type/Enum/EnumCaseObjectType.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
99
use PHPStan\Reflection\ClassMemberAccessAnswerer;
1010
use PHPStan\Reflection\ClassReflection;
11+
use PHPStan\Reflection\ExtendedPropertyReflection;
1112
use PHPStan\Reflection\Php\EnumPropertyReflection;
1213
use PHPStan\Reflection\Php\EnumUnresolvedPropertyPrototypeReflection;
1314
use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection;
@@ -127,10 +128,15 @@ public function tryRemove(Type $typeToRemove): ?Type
127128
}
128129

129130
public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
131+
{
132+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope);
133+
}
134+
135+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
130136
{
131137
$classReflection = $this->getClassReflection();
132138
if ($classReflection === null) {
133-
return parent::getUnresolvedPropertyPrototype($propertyName, $scope);
139+
return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope);
134140

135141
}
136142
if ($propertyName === 'name') {
@@ -153,7 +159,22 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
153159
}
154160
}
155161

156-
return parent::getUnresolvedPropertyPrototype($propertyName, $scope);
162+
return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope);
163+
}
164+
165+
public function hasStaticProperty(string $propertyName): TrinaryLogic
166+
{
167+
return TrinaryLogic::createNo();
168+
}
169+
170+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
171+
{
172+
throw new ShouldNotHappenException();
173+
}
174+
175+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
176+
{
177+
throw new ShouldNotHappenException();
157178
}
158179

159180
public function getBackingValueType(): ?Type

src/Type/Generic/GenericObjectType.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,30 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
232232
return $prototype->doNotResolveTemplateTypeMapToBounds();
233233
}
234234

235+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
236+
{
237+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty();
238+
}
239+
240+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
241+
{
242+
$prototype = parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope);
243+
244+
return $prototype->doNotResolveTemplateTypeMapToBounds();
245+
}
246+
247+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
248+
{
249+
return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty();
250+
}
251+
252+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
253+
{
254+
$prototype = parent::getUnresolvedStaticPropertyPrototype($propertyName, $scope);
255+
256+
return $prototype->doNotResolveTemplateTypeMapToBounds();
257+
}
258+
235259
public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): ExtendedMethodReflection
236260
{
237261
return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod();

src/Type/IntersectionType.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,72 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
533533
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
534534
}
535535

536+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
537+
{
538+
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasInstanceProperty($propertyName));
539+
}
540+
541+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
542+
{
543+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty();
544+
}
545+
546+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
547+
{
548+
$propertyPrototypes = [];
549+
foreach ($this->types as $type) {
550+
if (!$type->hasProperty($propertyName)->yes()) {
551+
continue;
552+
}
553+
554+
$propertyPrototypes[] = $type->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->withFechedOnType($this);
555+
}
556+
557+
$propertiesCount = count($propertyPrototypes);
558+
if ($propertiesCount === 0) {
559+
throw new ShouldNotHappenException();
560+
}
561+
562+
if ($propertiesCount === 1) {
563+
return $propertyPrototypes[0];
564+
}
565+
566+
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
567+
}
568+
569+
public function hasStaticProperty(string $propertyName): TrinaryLogic
570+
{
571+
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasStaticProperty($propertyName));
572+
}
573+
574+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
575+
{
576+
return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty();
577+
}
578+
579+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
580+
{
581+
$propertyPrototypes = [];
582+
foreach ($this->types as $type) {
583+
if (!$type->hasStaticProperty($propertyName)->yes()) {
584+
continue;
585+
}
586+
587+
$propertyPrototypes[] = $type->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->withFechedOnType($this);
588+
}
589+
590+
$propertiesCount = count($propertyPrototypes);
591+
if ($propertiesCount === 0) {
592+
throw new ShouldNotHappenException();
593+
}
594+
595+
if ($propertiesCount === 1) {
596+
return $propertyPrototypes[0];
597+
}
598+
599+
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
600+
}
601+
536602
public function canCallMethods(): TrinaryLogic
537603
{
538604
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->canCallMethods());

src/Type/MixedType.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,48 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
405405
);
406406
}
407407

408+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
409+
{
410+
return TrinaryLogic::createYes();
411+
}
412+
413+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
414+
{
415+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty();
416+
}
417+
418+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
419+
{
420+
$property = new DummyPropertyReflection();
421+
return new CallbackUnresolvedPropertyPrototypeReflection(
422+
$property,
423+
$property->getDeclaringClass(),
424+
false,
425+
static fn (Type $type): Type => $type,
426+
);
427+
}
428+
429+
public function hasStaticProperty(string $propertyName): TrinaryLogic
430+
{
431+
return TrinaryLogic::createYes();
432+
}
433+
434+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
435+
{
436+
return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty();
437+
}
438+
439+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
440+
{
441+
$property = new DummyPropertyReflection();
442+
return new CallbackUnresolvedPropertyPrototypeReflection(
443+
$property,
444+
$property->getDeclaringClass(),
445+
false,
446+
static fn (Type $type): Type => $type,
447+
);
448+
}
449+
408450
public function canCallMethods(): TrinaryLogic
409451
{
410452
return TrinaryLogic::createYes();

src/Type/NeverType.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,36 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
138138
throw new ShouldNotHappenException();
139139
}
140140

141+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
142+
{
143+
return TrinaryLogic::createNo();
144+
}
145+
146+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
147+
{
148+
throw new ShouldNotHappenException();
149+
}
150+
151+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
152+
{
153+
throw new ShouldNotHappenException();
154+
}
155+
156+
public function hasStaticProperty(string $propertyName): TrinaryLogic
157+
{
158+
return TrinaryLogic::createNo();
159+
}
160+
161+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
162+
{
163+
throw new ShouldNotHappenException();
164+
}
165+
166+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
167+
{
168+
throw new ShouldNotHappenException();
169+
}
170+
141171
public function canCallMethods(): TrinaryLogic
142172
{
143173
return TrinaryLogic::createYes();

src/Type/NonexistentParentClassType.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,36 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
7777
throw new ShouldNotHappenException();
7878
}
7979

80+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
81+
{
82+
return TrinaryLogic::createNo();
83+
}
84+
85+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
86+
{
87+
throw new ShouldNotHappenException();
88+
}
89+
90+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
91+
{
92+
throw new ShouldNotHappenException();
93+
}
94+
95+
public function hasStaticProperty(string $propertyName): TrinaryLogic
96+
{
97+
return TrinaryLogic::createNo();
98+
}
99+
100+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
101+
{
102+
throw new ShouldNotHappenException();
103+
}
104+
105+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
106+
{
107+
throw new ShouldNotHappenException();
108+
}
109+
80110
public function canCallMethods(): TrinaryLogic
81111
{
82112
return TrinaryLogic::createNo();

0 commit comments

Comments
 (0)