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\ConstantFloatType;
8: use PHPStan\Type\Constant\ConstantIntegerType;
9: use PHPStan\Type\ErrorType;
10: use PHPStan\Type\IntegerRangeType;
11: use PHPStan\Type\IntersectionType;
12: use PHPStan\Type\MixedType;
13: use PHPStan\Type\Traits\MaybeCallableTypeTrait;
14: use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
15: use PHPStan\Type\Traits\NonGenericTypeTrait;
16: use PHPStan\Type\Traits\NonObjectTypeTrait;
17: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
18: use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
19: use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
20: use PHPStan\Type\Type;
21: use PHPStan\Type\TypeCombinator;
22: use PHPStan\Type\UnionType;
23: use PHPStan\Type\VerbosityLevel;
24:
25: /** @api */
26: class AccessoryArrayListType implements CompoundType, AccessoryType
27: {
28:
29: use MaybeCallableTypeTrait;
30: use NonObjectTypeTrait;
31: use NonGenericTypeTrait;
32: use UndecidedBooleanTypeTrait;
33: use UndecidedComparisonCompoundTypeTrait;
34: use NonRemoveableTypeTrait;
35: use NonGeneralizableTypeTrait;
36:
37: private static bool $enabled = false;
38:
39: public function __construct()
40: {
41: }
42:
43: public function getReferencedClasses(): array
44: {
45: return [];
46: }
47:
48: public function getArrays(): array
49: {
50: return [];
51: }
52:
53: public function getConstantArrays(): array
54: {
55: return [];
56: }
57:
58: public function getConstantStrings(): array
59: {
60: return [];
61: }
62:
63: public function accepts(Type $type, bool $strictTypes): TrinaryLogic
64: {
65: if ($type instanceof CompoundType) {
66: return $type->isAcceptedBy($this, $strictTypes);
67: }
68:
69: return $type->isArray()
70: ->and($type->isList());
71: }
72:
73: public function isSuperTypeOf(Type $type): TrinaryLogic
74: {
75: if ($this->equals($type)) {
76: return TrinaryLogic::createYes();
77: }
78:
79: if ($type instanceof CompoundType) {
80: return $type->isSubTypeOf($this);
81: }
82:
83: return $type->isArray()
84: ->and($type->isList());
85: }
86:
87: public function isSubTypeOf(Type $otherType): TrinaryLogic
88: {
89: if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) {
90: return $otherType->isSuperTypeOf($this);
91: }
92:
93: return $otherType->isArray()
94: ->and($otherType->isList())
95: ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe());
96: }
97:
98: public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
99: {
100: return $this->isSubTypeOf($acceptingType);
101: }
102:
103: public function equals(Type $type): bool
104: {
105: return $type instanceof self;
106: }
107:
108: public function describe(VerbosityLevel $level): string
109: {
110: return 'list';
111: }
112:
113: public function isOffsetAccessible(): TrinaryLogic
114: {
115: return TrinaryLogic::createYes();
116: }
117:
118: public function hasOffsetValueType(Type $offsetType): TrinaryLogic
119: {
120: return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->and(TrinaryLogic::createMaybe());
121: }
122:
123: public function getOffsetValueType(Type $offsetType): Type
124: {
125: return new MixedType();
126: }
127:
128: public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
129: {
130: if ($offsetType === null || (new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) {
131: return $this;
132: }
133:
134: return new ErrorType();
135: }
136:
137: public function unsetOffset(Type $offsetType): Type
138: {
139: if ($this->hasOffsetValueType($offsetType)->no()) {
140: return $this;
141: }
142:
143: return new ErrorType();
144: }
145:
146: public function getKeysArray(): Type
147: {
148: return $this;
149: }
150:
151: public function getValuesArray(): Type
152: {
153: return $this;
154: }
155:
156: public function fillKeysArray(Type $valueType): Type
157: {
158: return new MixedType();
159: }
160:
161: public function flipArray(): Type
162: {
163: return new MixedType();
164: }
165:
166: public function intersectKeyArray(Type $otherArraysType): Type
167: {
168: if ($otherArraysType->isList()->yes()) {
169: return $this;
170: }
171:
172: return new MixedType();
173: }
174:
175: public function popArray(): Type
176: {
177: return $this;
178: }
179:
180: public function searchArray(Type $needleType): Type
181: {
182: return new MixedType();
183: }
184:
185: public function shiftArray(): Type
186: {
187: return $this;
188: }
189:
190: public function shuffleArray(): Type
191: {
192: return $this;
193: }
194:
195: public function isIterable(): TrinaryLogic
196: {
197: return TrinaryLogic::createYes();
198: }
199:
200: public function isIterableAtLeastOnce(): TrinaryLogic
201: {
202: return TrinaryLogic::createMaybe();
203: }
204:
205: public function getArraySize(): Type
206: {
207: return IntegerRangeType::fromInterval(0, null);
208: }
209:
210: public function getIterableKeyType(): Type
211: {
212: return IntegerRangeType::fromInterval(0, null);
213: }
214:
215: public function getFirstIterableKeyType(): Type
216: {
217: return new ConstantIntegerType(0);
218: }
219:
220: public function getLastIterableKeyType(): Type
221: {
222: return $this->getIterableKeyType();
223: }
224:
225: public function getIterableValueType(): Type
226: {
227: return new MixedType();
228: }
229:
230: public function getFirstIterableValueType(): Type
231: {
232: return new MixedType();
233: }
234:
235: public function getLastIterableValueType(): Type
236: {
237: return new MixedType();
238: }
239:
240: public function isArray(): TrinaryLogic
241: {
242: return TrinaryLogic::createYes();
243: }
244:
245: public function isConstantArray(): TrinaryLogic
246: {
247: return TrinaryLogic::createMaybe();
248: }
249:
250: public function isOversizedArray(): TrinaryLogic
251: {
252: return TrinaryLogic::createMaybe();
253: }
254:
255: public function isList(): TrinaryLogic
256: {
257: return TrinaryLogic::createYes();
258: }
259:
260: public function isNull(): TrinaryLogic
261: {
262: return TrinaryLogic::createNo();
263: }
264:
265: public function isTrue(): TrinaryLogic
266: {
267: return TrinaryLogic::createNo();
268: }
269:
270: public function isFalse(): TrinaryLogic
271: {
272: return TrinaryLogic::createNo();
273: }
274:
275: public function isBoolean(): TrinaryLogic
276: {
277: return TrinaryLogic::createNo();
278: }
279:
280: public function isFloat(): TrinaryLogic
281: {
282: return TrinaryLogic::createNo();
283: }
284:
285: public function isInteger(): TrinaryLogic
286: {
287: return TrinaryLogic::createNo();
288: }
289:
290: public function isString(): TrinaryLogic
291: {
292: return TrinaryLogic::createNo();
293: }
294:
295: public function isNumericString(): TrinaryLogic
296: {
297: return TrinaryLogic::createNo();
298: }
299:
300: public function isNonEmptyString(): TrinaryLogic
301: {
302: return TrinaryLogic::createNo();
303: }
304:
305: public function isNonFalsyString(): TrinaryLogic
306: {
307: return TrinaryLogic::createNo();
308: }
309:
310: public function isLiteralString(): TrinaryLogic
311: {
312: return TrinaryLogic::createNo();
313: }
314:
315: public function isClassStringType(): TrinaryLogic
316: {
317: return TrinaryLogic::createNo();
318: }
319:
320: public function isVoid(): TrinaryLogic
321: {
322: return TrinaryLogic::createNo();
323: }
324:
325: public function isScalar(): TrinaryLogic
326: {
327: return TrinaryLogic::createNo();
328: }
329:
330: public function toNumber(): Type
331: {
332: return new ErrorType();
333: }
334:
335: public function toInteger(): Type
336: {
337: return TypeCombinator::union(
338: new ConstantIntegerType(0),
339: new ConstantIntegerType(1),
340: );
341: }
342:
343: public function toFloat(): Type
344: {
345: return TypeCombinator::union(
346: new ConstantFloatType(0.0),
347: new ConstantFloatType(1.0),
348: );
349: }
350:
351: public function toString(): Type
352: {
353: return new ErrorType();
354: }
355:
356: public function toArray(): Type
357: {
358: return $this;
359: }
360:
361: public function toArrayKey(): Type
362: {
363: return new ErrorType();
364: }
365:
366: public function traverse(callable $cb): Type
367: {
368: return $this;
369: }
370:
371: public static function __set_state(array $properties): Type
372: {
373: return new self();
374: }
375:
376: public static function setListTypeEnabled(bool $enabled): void
377: {
378: self::$enabled = $enabled;
379: }
380:
381: public static function isListTypeEnabled(): bool
382: {
383: return self::$enabled;
384: }
385:
386: public static function intersectWith(Type $type): Type
387: {
388: if (self::$enabled) {
389: return TypeCombinator::intersect($type, new self());
390: }
391:
392: return $type;
393: }
394:
395: }
396: