1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type\Accessory;
4:
5: use PHPStan\Php\PhpVersion;
6: use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
7: use PHPStan\PhpDocParser\Ast\Type\TypeNode;
8: use PHPStan\TrinaryLogic;
9: use PHPStan\Type\AcceptsResult;
10: use PHPStan\Type\BooleanType;
11: use PHPStan\Type\CompoundType;
12: use PHPStan\Type\Constant\ConstantFloatType;
13: use PHPStan\Type\Constant\ConstantIntegerType;
14: use PHPStan\Type\ErrorType;
15: use PHPStan\Type\IntegerRangeType;
16: use PHPStan\Type\IntersectionType;
17: use PHPStan\Type\IsSuperTypeOfResult;
18: use PHPStan\Type\MixedType;
19: use PHPStan\Type\Traits\MaybeCallableTypeTrait;
20: use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
21: use PHPStan\Type\Traits\NonGenericTypeTrait;
22: use PHPStan\Type\Traits\NonObjectTypeTrait;
23: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
24: use PHPStan\Type\Traits\UndecidedBooleanTypeTrait;
25: use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
26: use PHPStan\Type\Type;
27: use PHPStan\Type\TypeCombinator;
28: use PHPStan\Type\UnionType;
29: use PHPStan\Type\VerbosityLevel;
30:
31: /** @api */
32: class AccessoryArrayListType implements CompoundType, AccessoryType
33: {
34:
35: use MaybeCallableTypeTrait;
36: use NonObjectTypeTrait;
37: use NonGenericTypeTrait;
38: use UndecidedBooleanTypeTrait;
39: use UndecidedComparisonCompoundTypeTrait;
40: use NonRemoveableTypeTrait;
41: use NonGeneralizableTypeTrait;
42:
43: /** @api */
44: public function __construct()
45: {
46: }
47:
48: public function getReferencedClasses(): array
49: {
50: return [];
51: }
52:
53: public function getObjectClassNames(): array
54: {
55: return [];
56: }
57:
58: public function getObjectClassReflections(): array
59: {
60: return [];
61: }
62:
63: public function getArrays(): array
64: {
65: return [];
66: }
67:
68: public function getConstantArrays(): array
69: {
70: return [];
71: }
72:
73: public function getConstantStrings(): array
74: {
75: return [];
76: }
77:
78: public function accepts(Type $type, bool $strictTypes): AcceptsResult
79: {
80: if ($type instanceof CompoundType) {
81: return $type->isAcceptedBy($this, $strictTypes);
82: }
83:
84: $isArray = $type->isArray();
85: $isList = $type->isList();
86:
87: return new AcceptsResult($isArray->and($isList), []);
88: }
89:
90: public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
91: {
92: if ($this->equals($type)) {
93: return IsSuperTypeOfResult::createYes();
94: }
95:
96: if ($type instanceof CompoundType) {
97: return $type->isSubTypeOf($this);
98: }
99:
100: return new IsSuperTypeOfResult($type->isArray()->and($type->isList()), []);
101: }
102:
103: public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult
104: {
105: if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) {
106: return $otherType->isSuperTypeOf($this);
107: }
108:
109: return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isList()), []))
110: ->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe());
111: }
112:
113: public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult
114: {
115: return $this->isSubTypeOf($acceptingType)->toAcceptsResult();
116: }
117:
118: public function equals(Type $type): bool
119: {
120: return $type instanceof self;
121: }
122:
123: public function describe(VerbosityLevel $level): string
124: {
125: return 'list';
126: }
127:
128: public function isOffsetAccessible(): TrinaryLogic
129: {
130: return TrinaryLogic::createYes();
131: }
132:
133: public function isOffsetAccessLegal(): TrinaryLogic
134: {
135: return TrinaryLogic::createYes();
136: }
137:
138: public function hasOffsetValueType(Type $offsetType): TrinaryLogic
139: {
140: return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->result->and(TrinaryLogic::createMaybe());
141: }
142:
143: public function getOffsetValueType(Type $offsetType): Type
144: {
145: return new MixedType();
146: }
147:
148: public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
149: {
150: if ($offsetType === null || (new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) {
151: return $this;
152: }
153:
154: return new ErrorType();
155: }
156:
157: public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type
158: {
159: return $this;
160: }
161:
162: public function unsetOffset(Type $offsetType): Type
163: {
164: if ($this->hasOffsetValueType($offsetType)->no()) {
165: return $this;
166: }
167:
168: return new ErrorType();
169: }
170:
171: public function getKeysArrayFiltered(Type $filterValueType, TrinaryLogic $strict): Type
172: {
173: return $this->getKeysArray();
174: }
175:
176: public function getKeysArray(): Type
177: {
178: return $this;
179: }
180:
181: public function getValuesArray(): Type
182: {
183: return $this;
184: }
185:
186: public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type
187: {
188: return $this;
189: }
190:
191: public function fillKeysArray(Type $valueType): Type
192: {
193: return new MixedType();
194: }
195:
196: public function flipArray(): Type
197: {
198: return new MixedType();
199: }
200:
201: public function intersectKeyArray(Type $otherArraysType): Type
202: {
203: if ($otherArraysType->isList()->yes()) {
204: return $this;
205: }
206:
207: return new MixedType();
208: }
209:
210: public function popArray(): Type
211: {
212: return $this;
213: }
214:
215: public function reverseArray(TrinaryLogic $preserveKeys): Type
216: {
217: if ($preserveKeys->no()) {
218: return $this;
219: }
220:
221: return new MixedType();
222: }
223:
224: public function searchArray(Type $needleType, ?TrinaryLogic $strict = null): Type
225: {
226: return new MixedType();
227: }
228:
229: public function shiftArray(): Type
230: {
231: return $this;
232: }
233:
234: public function shuffleArray(): Type
235: {
236: return $this;
237: }
238:
239: public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys): Type
240: {
241: if ($preserveKeys->no()) {
242: return $this;
243: }
244:
245: if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) {
246: return $this;
247: }
248:
249: return new MixedType();
250: }
251:
252: public function spliceArray(Type $offsetType, Type $lengthType, Type $replacementType): Type
253: {
254: return $this;
255: }
256:
257: public function isIterable(): TrinaryLogic
258: {
259: return TrinaryLogic::createYes();
260: }
261:
262: public function isIterableAtLeastOnce(): TrinaryLogic
263: {
264: return TrinaryLogic::createMaybe();
265: }
266:
267: public function getArraySize(): Type
268: {
269: return IntegerRangeType::fromInterval(0, null);
270: }
271:
272: public function getIterableKeyType(): Type
273: {
274: return IntegerRangeType::fromInterval(0, null);
275: }
276:
277: public function getFirstIterableKeyType(): Type
278: {
279: return new ConstantIntegerType(0);
280: }
281:
282: public function getLastIterableKeyType(): Type
283: {
284: return $this->getIterableKeyType();
285: }
286:
287: public function getIterableValueType(): Type
288: {
289: return new MixedType();
290: }
291:
292: public function getFirstIterableValueType(): Type
293: {
294: return new MixedType();
295: }
296:
297: public function getLastIterableValueType(): Type
298: {
299: return new MixedType();
300: }
301:
302: public function isArray(): TrinaryLogic
303: {
304: return TrinaryLogic::createYes();
305: }
306:
307: public function isConstantArray(): TrinaryLogic
308: {
309: return TrinaryLogic::createMaybe();
310: }
311:
312: public function isOversizedArray(): TrinaryLogic
313: {
314: return TrinaryLogic::createMaybe();
315: }
316:
317: public function isList(): TrinaryLogic
318: {
319: return TrinaryLogic::createYes();
320: }
321:
322: public function isNull(): TrinaryLogic
323: {
324: return TrinaryLogic::createNo();
325: }
326:
327: public function isConstantValue(): TrinaryLogic
328: {
329: return TrinaryLogic::createMaybe();
330: }
331:
332: public function isConstantScalarValue(): TrinaryLogic
333: {
334: return TrinaryLogic::createNo();
335: }
336:
337: public function getConstantScalarTypes(): array
338: {
339: return [];
340: }
341:
342: public function getConstantScalarValues(): array
343: {
344: return [];
345: }
346:
347: public function isTrue(): TrinaryLogic
348: {
349: return TrinaryLogic::createNo();
350: }
351:
352: public function isFalse(): TrinaryLogic
353: {
354: return TrinaryLogic::createNo();
355: }
356:
357: public function isBoolean(): TrinaryLogic
358: {
359: return TrinaryLogic::createNo();
360: }
361:
362: public function isFloat(): TrinaryLogic
363: {
364: return TrinaryLogic::createNo();
365: }
366:
367: public function isInteger(): TrinaryLogic
368: {
369: return TrinaryLogic::createNo();
370: }
371:
372: public function isString(): TrinaryLogic
373: {
374: return TrinaryLogic::createNo();
375: }
376:
377: public function isNumericString(): TrinaryLogic
378: {
379: return TrinaryLogic::createNo();
380: }
381:
382: public function isNonEmptyString(): TrinaryLogic
383: {
384: return TrinaryLogic::createNo();
385: }
386:
387: public function isNonFalsyString(): TrinaryLogic
388: {
389: return TrinaryLogic::createNo();
390: }
391:
392: public function isLiteralString(): TrinaryLogic
393: {
394: return TrinaryLogic::createNo();
395: }
396:
397: public function isLowercaseString(): TrinaryLogic
398: {
399: return TrinaryLogic::createNo();
400: }
401:
402: public function isClassString(): TrinaryLogic
403: {
404: return TrinaryLogic::createNo();
405: }
406:
407: public function isUppercaseString(): TrinaryLogic
408: {
409: return TrinaryLogic::createNo();
410: }
411:
412: public function getClassStringObjectType(): Type
413: {
414: return new ErrorType();
415: }
416:
417: public function getObjectTypeOrClassStringObjectType(): Type
418: {
419: return new ErrorType();
420: }
421:
422: public function isVoid(): TrinaryLogic
423: {
424: return TrinaryLogic::createNo();
425: }
426:
427: public function isScalar(): TrinaryLogic
428: {
429: return TrinaryLogic::createNo();
430: }
431:
432: public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
433: {
434: return new BooleanType();
435: }
436:
437: public function toNumber(): Type
438: {
439: return new ErrorType();
440: }
441:
442: public function toAbsoluteNumber(): Type
443: {
444: return new ErrorType();
445: }
446:
447: public function toInteger(): Type
448: {
449: return TypeCombinator::union(
450: new ConstantIntegerType(0),
451: new ConstantIntegerType(1),
452: );
453: }
454:
455: public function toFloat(): Type
456: {
457: return TypeCombinator::union(
458: new ConstantFloatType(0.0),
459: new ConstantFloatType(1.0),
460: );
461: }
462:
463: public function toString(): Type
464: {
465: return new ErrorType();
466: }
467:
468: public function toArray(): Type
469: {
470: return $this;
471: }
472:
473: public function toArrayKey(): Type
474: {
475: return new ErrorType();
476: }
477:
478: public function toCoercedArgumentType(bool $strictTypes): Type
479: {
480: return $this;
481: }
482:
483: public function traverse(callable $cb): Type
484: {
485: return $this;
486: }
487:
488: public function traverseSimultaneously(Type $right, callable $cb): Type
489: {
490: return $this;
491: }
492:
493: public function exponentiate(Type $exponent): Type
494: {
495: return new ErrorType();
496: }
497:
498: public function getFiniteTypes(): array
499: {
500: return [];
501: }
502:
503: public function toPhpDocNode(): TypeNode
504: {
505: return new IdentifierTypeNode('list');
506: }
507:
508: }
509: