Skip to content

Commit caae407

Browse files
Introduce new methods
1 parent f19e8bc commit caae407

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
@@ -6149,7 +6149,10 @@ private function methodCallReturnType(Type $typeWithMethod, string $methodName,
61496149
return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $methodCall);
61506150
}
61516151

6152-
/** @api */
6152+
/**
6153+
* @api
6154+
* @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead
6155+
*/
61536156
public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
61546157
{
61556158
if ($typeWithProperty instanceof UnionType) {
@@ -6162,6 +6165,32 @@ public function getPropertyReflection(Type $typeWithProperty, string $propertyNa
61626165
return $typeWithProperty->getProperty($propertyName, $this);
61636166
}
61646167

6168+
/** @api */
6169+
public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6170+
{
6171+
if ($typeWithProperty instanceof UnionType) {
6172+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasInstanceProperty($propertyName)->yes());
6173+
}
6174+
if (!$typeWithProperty->hasInstanceProperty($propertyName)->yes()) {
6175+
return null;
6176+
}
6177+
6178+
return $typeWithProperty->getInstanceProperty($propertyName, $this);
6179+
}
6180+
6181+
/** @api */
6182+
public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6183+
{
6184+
if ($typeWithProperty instanceof UnionType) {
6185+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasStaticProperty($propertyName)->yes());
6186+
}
6187+
if (!$typeWithProperty->hasStaticProperty($propertyName)->yes()) {
6188+
return null;
6189+
}
6190+
6191+
return $typeWithProperty->getStaticProperty($propertyName, $this);
6192+
}
6193+
61656194
/**
61666195
* @param PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch
61676196
*/

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
@@ -316,6 +316,36 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
316316
return $this->objectType->getUnresolvedPropertyPrototype($propertyName, $scope);
317317
}
318318

319+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
320+
{
321+
return $this->objectType->hasInstanceProperty($propertyName);
322+
}
323+
324+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
325+
{
326+
return $this->objectType->getInstanceProperty($propertyName, $scope);
327+
}
328+
329+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
330+
{
331+
return $this->objectType->getUnresolvedInstancePropertyPrototype($propertyName, $scope);
332+
}
333+
334+
public function hasStaticProperty(string $propertyName): TrinaryLogic
335+
{
336+
return $this->objectType->hasStaticProperty($propertyName);
337+
}
338+
339+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
340+
{
341+
return $this->objectType->getStaticProperty($propertyName, $scope);
342+
}
343+
344+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
345+
{
346+
return $this->objectType->getUnresolvedStaticPropertyPrototype($propertyName, $scope);
347+
}
348+
319349
public function canCallMethods(): TrinaryLogic
320350
{
321351
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
@@ -535,6 +535,72 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
535535
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
536536
}
537537

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

423+
public function hasInstanceProperty(string $propertyName): TrinaryLogic
424+
{
425+
return TrinaryLogic::createYes();
426+
}
427+
428+
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
429+
{
430+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope)->getTransformedProperty();
431+
}
432+
433+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
434+
{
435+
$property = new DummyPropertyReflection();
436+
return new CallbackUnresolvedPropertyPrototypeReflection(
437+
$property,
438+
$property->getDeclaringClass(),
439+
false,
440+
static fn (Type $type): Type => $type,
441+
);
442+
}
443+
444+
public function hasStaticProperty(string $propertyName): TrinaryLogic
445+
{
446+
return TrinaryLogic::createYes();
447+
}
448+
449+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
450+
{
451+
return $this->getUnresolvedStaticPropertyPrototype($propertyName, $scope)->getTransformedProperty();
452+
}
453+
454+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
455+
{
456+
$property = new DummyPropertyReflection();
457+
return new CallbackUnresolvedPropertyPrototypeReflection(
458+
$property,
459+
$property->getDeclaringClass(),
460+
false,
461+
static fn (Type $type): Type => $type,
462+
);
463+
}
464+
423465
public function canCallMethods(): TrinaryLogic
424466
{
425467
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)