1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type\Accessory;
4:
5: use PHPStan\TrinaryLogic;
6: use PHPStan\Type\CompoundType;
7: use PHPStan\Type\Constant\ConstantArrayType;
8: use PHPStan\Type\Constant\ConstantIntegerType;
9: use PHPStan\Type\ErrorType;
10: use PHPStan\Type\FloatType;
11: use PHPStan\Type\GeneralizePrecision;
12: use PHPStan\Type\IntegerRangeType;
13: use PHPStan\Type\IntegerType;
14: use PHPStan\Type\IntersectionType;
15: use PHPStan\Type\StringType;
16: use PHPStan\Type\Traits\MaybeCallableTypeTrait;
17: use PHPStan\Type\Traits\NonGenericTypeTrait;
18: use PHPStan\Type\Traits\NonIterableTypeTrait;
19: use PHPStan\Type\Traits\NonObjectTypeTrait;
20: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
21: use PHPStan\Type\Traits\TruthyBooleanTypeTrait;
22: use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
23: use PHPStan\Type\Type;
24: use PHPStan\Type\UnionType;
25: use PHPStan\Type\VerbosityLevel;
26:
27: class AccessoryNonFalsyStringType implements CompoundType, AccessoryType
28: {
29:
30: use MaybeCallableTypeTrait;
31: use NonObjectTypeTrait;
32: use NonIterableTypeTrait;
33: use TruthyBooleanTypeTrait;
34: use UndecidedComparisonCompoundTypeTrait;
35: use NonGenericTypeTrait;
36: use NonRemoveableTypeTrait;
37:
38: /** @api */
39: public function __construct()
40: {
41: }
42:
43: public function getReferencedClasses(): array
44: {
45: return [];
46: }
47:
48: public function accepts(Type $type, bool $strictTypes): TrinaryLogic
49: {
50: if ($type instanceof CompoundType) {
51: return $type->isAcceptedBy($this, $strictTypes);
52: }
53:
54: return $type->isNonFalsyString();
55: }
56:
57: public function isSuperTypeOf(Type $type): TrinaryLogic
58: {
59: if ($type instanceof CompoundType) {
60: return $type->isSubTypeOf($this);
61: }
62:
63: if ($this->equals($type)) {
64: return TrinaryLogic::createYes();
65: }
66:
67: return $type->isNonFalsyString();
68: }
69:
70: public function isSubTypeOf(Type $otherType): TrinaryLogic
71: {
72: if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) {
73: return $otherType->isSuperTypeOf($this);
74: }
75:
76: if ($otherType instanceof AccessoryNonEmptyStringType) {
77: return TrinaryLogic::createYes();
78: }
79:
80: return $otherType->isNonFalsyString()
81: ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe());
82: }
83:
84: public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
85: {
86: return $this->isSubTypeOf($acceptingType);
87: }
88:
89: public function equals(Type $type): bool
90: {
91: return $type instanceof self;
92: }
93:
94: public function describe(VerbosityLevel $level): string
95: {
96: return 'non-falsy-string';
97: }
98:
99: public function isOffsetAccessible(): TrinaryLogic
100: {
101: return TrinaryLogic::createYes();
102: }
103:
104: public function hasOffsetValueType(Type $offsetType): TrinaryLogic
105: {
106: return (new IntegerType())->isSuperTypeOf($offsetType)->and(TrinaryLogic::createMaybe());
107: }
108:
109: public function getOffsetValueType(Type $offsetType): Type
110: {
111: if ($this->hasOffsetValueType($offsetType)->no()) {
112: return new ErrorType();
113: }
114:
115: if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) {
116: return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]);
117: }
118:
119: return new StringType();
120: }
121:
122: public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
123: {
124: return $this;
125: }
126:
127: public function unsetOffset(Type $offsetType): Type
128: {
129: return new ErrorType();
130: }
131:
132: public function isArray(): TrinaryLogic
133: {
134: return TrinaryLogic::createNo();
135: }
136:
137: public function isOversizedArray(): TrinaryLogic
138: {
139: return TrinaryLogic::createNo();
140: }
141:
142: public function toNumber(): Type
143: {
144: return new ErrorType();
145: }
146:
147: public function toInteger(): Type
148: {
149: return new UnionType([
150: IntegerRangeType::fromInterval(null, -1),
151: IntegerRangeType::fromInterval(1, null),
152: ]);
153: }
154:
155: public function toFloat(): Type
156: {
157: return new FloatType();
158: }
159:
160: public function toString(): Type
161: {
162: return $this;
163: }
164:
165: public function toArray(): Type
166: {
167: return new ConstantArrayType(
168: [new ConstantIntegerType(0)],
169: [$this],
170: [1],
171: );
172: }
173:
174: public function isString(): TrinaryLogic
175: {
176: return TrinaryLogic::createYes();
177: }
178:
179: public function isNumericString(): TrinaryLogic
180: {
181: return TrinaryLogic::createMaybe();
182: }
183:
184: public function isNonEmptyString(): TrinaryLogic
185: {
186: return TrinaryLogic::createYes();
187: }
188:
189: public function isNonFalsyString(): TrinaryLogic
190: {
191: return TrinaryLogic::createYes();
192: }
193:
194: public function isLiteralString(): TrinaryLogic
195: {
196: return TrinaryLogic::createMaybe();
197: }
198:
199: public function traverse(callable $cb): Type
200: {
201: return $this;
202: }
203:
204: public function generalize(GeneralizePrecision $precision): Type
205: {
206: return new StringType();
207: }
208:
209: public static function __set_state(array $properties): Type
210: {
211: return new self();
212: }
213:
214: }
215: