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