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