Skip to content

Commit be5cf4d

Browse files
Introduce new methods
1 parent 2151184 commit be5cf4d

20 files changed

+838
-6
lines changed

src/Analyser/MutatingScope.php

+30-1
Original file line numberDiff line numberDiff line change
@@ -6062,7 +6062,10 @@ private function methodCallReturnType(Type $typeWithMethod, string $methodName,
60626062
return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $methodCall);
60636063
}
60646064

6065-
/** @api */
6065+
/**
6066+
* @api
6067+
* @deprecated Use getInstancePropertyReflection or getStaticPropertyReflection instead
6068+
*/
60666069
public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
60676070
{
60686071
if ($typeWithProperty instanceof UnionType) {
@@ -6075,6 +6078,32 @@ public function getPropertyReflection(Type $typeWithProperty, string $propertyNa
60756078
return $typeWithProperty->getProperty($propertyName, $this);
60766079
}
60776080

6081+
/** @api */
6082+
public function getInstancePropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6083+
{
6084+
if ($typeWithProperty instanceof UnionType) {
6085+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasInstanceProperty($propertyName)->yes());
6086+
}
6087+
if (!$typeWithProperty->hasInstanceProperty($propertyName)->yes()) {
6088+
return null;
6089+
}
6090+
6091+
return $typeWithProperty->getInstanceProperty($propertyName, $this);
6092+
}
6093+
6094+
/** @api */
6095+
public function getStaticPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection
6096+
{
6097+
if ($typeWithProperty instanceof UnionType) {
6098+
$typeWithProperty = $typeWithProperty->filterTypes(static fn (Type $innerType) => $innerType->hasStaticProperty($propertyName)->yes());
6099+
}
6100+
if (!$typeWithProperty->hasStaticProperty($propertyName)->yes()) {
6101+
return null;
6102+
}
6103+
6104+
return $typeWithProperty->getStaticProperty($propertyName, $this);
6105+
}
6106+
60786107
/**
60796108
* @param PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch
60806109
*/

src/Analyser/Scope.php

+5
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

+30
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

+23-2
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;
@@ -122,10 +123,15 @@ public function tryRemove(Type $typeToRemove): ?Type
122123
}
123124

124125
public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
126+
{
127+
return $this->getUnresolvedInstancePropertyPrototype($propertyName, $scope);
128+
}
129+
130+
public function getUnresolvedInstancePropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
125131
{
126132
$classReflection = $this->getClassReflection();
127133
if ($classReflection === null) {
128-
return parent::getUnresolvedPropertyPrototype($propertyName, $scope);
134+
return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope);
129135

130136
}
131137
if ($propertyName === 'name') {
@@ -148,7 +154,22 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
148154
}
149155
}
150156

151-
return parent::getUnresolvedPropertyPrototype($propertyName, $scope);
157+
return parent::getUnresolvedInstancePropertyPrototype($propertyName, $scope);
158+
}
159+
160+
public function hasStaticProperty(string $propertyName): TrinaryLogic
161+
{
162+
return TrinaryLogic::createNo();
163+
}
164+
165+
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
166+
{
167+
throw new ShouldNotHappenException();
168+
}
169+
170+
public function getUnresolvedStaticPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection
171+
{
172+
throw new ShouldNotHappenException();
152173
}
153174

154175
public function getBackingValueType(): ?Type

src/Type/Generic/GenericObjectType.php

+24
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

+66
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

+42
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

+30
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

+30
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)