1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Reflection\Php;
4:
5: use PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType;
6: use PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType;
7: use PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty;
8: use PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType;
9: use PHPStan\Reflection\ClassReflection;
10: use PHPStan\Reflection\ExtendedPropertyReflection;
11: use PHPStan\TrinaryLogic;
12: use PHPStan\Type\MixedType;
13: use PHPStan\Type\Type;
14: use PHPStan\Type\TypehintHelper;
15:
16: /**
17: * @api
18: * @final
19: */
20: class PhpPropertyReflection implements ExtendedPropertyReflection
21: {
22:
23: private ?Type $finalNativeType = null;
24:
25: private ?Type $type = null;
26:
27: public function __construct(
28: private ClassReflection $declaringClass,
29: private ?ClassReflection $declaringTrait,
30: private ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null $nativeType,
31: private ?Type $phpDocType,
32: private ReflectionProperty $reflection,
33: private ?string $deprecatedDescription,
34: private bool $isDeprecated,
35: private bool $isInternal,
36: private bool $isReadOnlyByPhpDoc,
37: private bool $isAllowedPrivateMutation,
38: )
39: {
40: }
41:
42: public function getDeclaringClass(): ClassReflection
43: {
44: return $this->declaringClass;
45: }
46:
47: public function getDeclaringTrait(): ?ClassReflection
48: {
49: return $this->declaringTrait;
50: }
51:
52: public function getDocComment(): ?string
53: {
54: $docComment = $this->reflection->getDocComment();
55: if ($docComment === false) {
56: return null;
57: }
58:
59: return $docComment;
60: }
61:
62: public function isStatic(): bool
63: {
64: return $this->reflection->isStatic();
65: }
66:
67: public function isPrivate(): bool
68: {
69: return $this->reflection->isPrivate();
70: }
71:
72: public function isPublic(): bool
73: {
74: return $this->reflection->isPublic();
75: }
76:
77: public function isReadOnly(): bool
78: {
79: return $this->reflection->isReadOnly();
80: }
81:
82: public function isReadOnlyByPhpDoc(): bool
83: {
84: return $this->isReadOnlyByPhpDoc;
85: }
86:
87: public function getReadableType(): Type
88: {
89: if ($this->type === null) {
90: $this->type = TypehintHelper::decideTypeFromReflection(
91: $this->nativeType,
92: $this->phpDocType,
93: $this->declaringClass,
94: );
95: }
96:
97: return $this->type;
98: }
99:
100: public function getWritableType(): Type
101: {
102: return $this->getReadableType();
103: }
104:
105: public function canChangeTypeAfterAssignment(): bool
106: {
107: return true;
108: }
109:
110: public function isPromoted(): bool
111: {
112: return $this->reflection->isPromoted();
113: }
114:
115: public function hasPhpDocType(): bool
116: {
117: return $this->phpDocType !== null;
118: }
119:
120: public function getPhpDocType(): Type
121: {
122: if ($this->phpDocType !== null) {
123: return $this->phpDocType;
124: }
125:
126: return new MixedType();
127: }
128:
129: public function hasNativeType(): bool
130: {
131: return $this->nativeType !== null;
132: }
133:
134: public function getNativeType(): Type
135: {
136: if ($this->finalNativeType === null) {
137: $this->finalNativeType = TypehintHelper::decideTypeFromReflection(
138: $this->nativeType,
139: null,
140: $this->declaringClass,
141: );
142: }
143:
144: return $this->finalNativeType;
145: }
146:
147: public function isReadable(): bool
148: {
149: return true;
150: }
151:
152: public function isWritable(): bool
153: {
154: return true;
155: }
156:
157: public function getDeprecatedDescription(): ?string
158: {
159: if ($this->isDeprecated) {
160: return $this->deprecatedDescription;
161: }
162:
163: return null;
164: }
165:
166: public function isDeprecated(): TrinaryLogic
167: {
168: return TrinaryLogic::createFromBoolean($this->isDeprecated);
169: }
170:
171: public function isInternal(): TrinaryLogic
172: {
173: return TrinaryLogic::createFromBoolean($this->isInternal);
174: }
175:
176: public function isAllowedPrivateMutation(): bool
177: {
178: return $this->isAllowedPrivateMutation;
179: }
180:
181: public function getNativeReflection(): ReflectionProperty
182: {
183: return $this->reflection;
184: }
185:
186: }
187: