1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type\Accessory;
4:
5: use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
6: use PHPStan\PhpDocParser\Ast\Type\TypeNode;
7: use PHPStan\Reflection\ClassMemberAccessAnswerer;
8: use PHPStan\Reflection\TrivialParametersAcceptor;
9: use PHPStan\TrinaryLogic;
10: use PHPStan\Type\AcceptsResult;
11: use PHPStan\Type\CompoundType;
12: use PHPStan\Type\ErrorType;
13: use PHPStan\Type\IntersectionType;
14: use PHPStan\Type\IsSuperTypeOfResult;
15: use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
16: use PHPStan\Type\Traits\NonGenericTypeTrait;
17: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
18: use PHPStan\Type\Traits\ObjectTypeTrait;
19: use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
20: use PHPStan\Type\Type;
21: use PHPStan\Type\UnionType;
22: use PHPStan\Type\VerbosityLevel;
23: use function sprintf;
24:
25: class HasPropertyType implements AccessoryType, CompoundType
26: {
27:
28: use ObjectTypeTrait;
29: use NonGenericTypeTrait;
30: use UndecidedComparisonCompoundTypeTrait;
31: use NonRemoveableTypeTrait;
32: use NonGeneralizableTypeTrait;
33:
34: /** @api */
35: public function __construct(private string $propertyName)
36: {
37: }
38:
39: public function getReferencedClasses(): array
40: {
41: return [];
42: }
43:
44: public function getObjectClassNames(): array
45: {
46: return [];
47: }
48:
49: public function getObjectClassReflections(): array
50: {
51: return [];
52: }
53:
54: public function getConstantStrings(): array
55: {
56: return [];
57: }
58:
59: public function getPropertyName(): string
60: {
61: return $this->propertyName;
62: }
63:
64: public function accepts(Type $type, bool $strictTypes): AcceptsResult
65: {
66: if ($type instanceof CompoundType) {
67: return $type->isAcceptedBy($this, $strictTypes);
68: }
69:
70: return AcceptsResult::createFromBoolean($this->equals($type));
71: }
72:
73: public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
74: {
75: return new IsSuperTypeOfResult($type->hasProperty($this->propertyName), []);
76: }
77:
78: public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult
79: {
80: if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) {
81: return $otherType->isSuperTypeOf($this);
82: }
83:
84: if ($otherType instanceof self) {
85: $limit = IsSuperTypeOfResult::createYes();
86: } else {
87: $limit = IsSuperTypeOfResult::createMaybe();
88: }
89:
90: return $limit->and(new IsSuperTypeOfResult($otherType->hasProperty($this->propertyName), []));
91: }
92:
93: public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult
94: {
95: return $this->isSubTypeOf($acceptingType)->toAcceptsResult();
96: }
97:
98: public function equals(Type $type): bool
99: {
100: return $type instanceof self
101: && $this->propertyName === $type->propertyName;
102: }
103:
104: public function describe(VerbosityLevel $level): string
105: {
106: return sprintf('hasProperty(%s)', $this->propertyName);
107: }
108:
109: public function isOffsetAccessLegal(): TrinaryLogic
110: {
111: return TrinaryLogic::createMaybe();
112: }
113:
114: public function hasProperty(string $propertyName): TrinaryLogic
115: {
116: if ($this->propertyName === $propertyName) {
117: return TrinaryLogic::createYes();
118: }
119:
120: return TrinaryLogic::createMaybe();
121: }
122:
123: public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array
124: {
125: return [new TrivialParametersAcceptor()];
126: }
127:
128: public function getEnumCases(): array
129: {
130: return [];
131: }
132:
133: public function traverse(callable $cb): Type
134: {
135: return $this;
136: }
137:
138: public function traverseSimultaneously(Type $right, callable $cb): Type
139: {
140: return $this;
141: }
142:
143: public function exponentiate(Type $exponent): Type
144: {
145: return new ErrorType();
146: }
147:
148: public function getFiniteTypes(): array
149: {
150: return [];
151: }
152:
153: public function toPhpDocNode(): TypeNode
154: {
155: return new IdentifierTypeNode(''); // no PHPDoc representation
156: }
157:
158: }
159: