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