Repository navigation
Expand file tree
/
Copy pathCalledOnTypeUnresolvedPropertyPrototypeReflection.php
More file actions
106 lines (88 loc) · 3.53 KB
/
Copy pathCalledOnTypeUnresolvedPropertyPrototypeReflection.php
File metadata and controls
106 lines (88 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php declare(strict_types = 1);
namespace PHPStan\Reflection\Type;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\Dummy\ChangedTypePropertyReflection;
use PHPStan\Reflection\ExtendedPropertyReflection;
use PHPStan\Reflection\ResolvedPropertyReflection;
use PHPStan\Turbo\ShadowedByTurboExtension;
use PHPStan\Type\Generic\GenericStaticType;
use PHPStan\Type\StaticType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use function count;
#[ShadowedByTurboExtension(implementation: __DIR__ . '/../../../turbo-ext/src/CalledOnTypeUnresolvedPropertyPrototypeReflection.cpp')]
final class CalledOnTypeUnresolvedPropertyPrototypeReflection implements UnresolvedPropertyPrototypeReflection
{
private ?ExtendedPropertyReflection $transformedProperty = null;
private ?self $cachedDoNotResolveTemplateTypeMapToBounds = null;
public function __construct(
private ExtendedPropertyReflection $propertyReflection,
private ClassReflection $resolvedDeclaringClass,
private bool $resolveTemplateTypeMapToBounds,
private Type $fetchedOnType,
)
{
}
public function doNotResolveTemplateTypeMapToBounds(): UnresolvedPropertyPrototypeReflection
{
if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) {
return $this->cachedDoNotResolveTemplateTypeMapToBounds;
}
return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(
$this->propertyReflection,
$this->resolvedDeclaringClass,
false,
$this->fetchedOnType,
);
}
public function getNakedProperty(): ExtendedPropertyReflection
{
return $this->propertyReflection;
}
public function getTransformedProperty(): ExtendedPropertyReflection
{
if ($this->transformedProperty !== null) {
return $this->transformedProperty;
}
$templateTypeMap = $this->resolvedDeclaringClass->getActiveTemplateTypeMap();
$callSiteVarianceMap = $this->resolvedDeclaringClass->getCallSiteVarianceMap();
return $this->transformedProperty = new ResolvedPropertyReflection(
$this->transformPropertyWithStaticType($this->resolvedDeclaringClass, $this->propertyReflection),
$this->resolveTemplateTypeMapToBounds ? $templateTypeMap->resolveToBounds() : $templateTypeMap,
$callSiteVarianceMap,
);
}
public function withFechedOnType(Type $type): UnresolvedPropertyPrototypeReflection
{
return new self(
$this->propertyReflection,
$this->resolvedDeclaringClass,
$this->resolveTemplateTypeMapToBounds,
$type,
);
}
private function transformPropertyWithStaticType(ClassReflection $declaringClass, ExtendedPropertyReflection $property): ExtendedPropertyReflection
{
$readableType = $this->transformStaticType($property->getReadableType());
$writableType = $this->transformStaticType($property->getWritableType());
$phpDocType = $this->transformStaticType($property->getPhpDocType());
$nativeType = $this->transformStaticType($property->getNativeType());
return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType, $phpDocType, $nativeType);
}
private function transformStaticType(Type $type): Type
{
return TypeTraverser::map($type, function (Type $type, callable $traverse): Type {
if ($type instanceof GenericStaticType) {
$fetchedOnTypeReflections = $this->fetchedOnType->getObjectClassReflections();
if (count($fetchedOnTypeReflections) === 1) {
return $traverse($type->changeBaseClass($fetchedOnTypeReflections[0])->getStaticObjectType());
}
return $this->fetchedOnType;
}
if ($type instanceof StaticType) {
return $this->fetchedOnType;
}
return $traverse($type);
});
}
}