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