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\Turbo\ShadowedByTurboExtension;
10: use PHPStan\Type\AcceptsResult;
11: use PHPStan\Type\BenevolentUnionType;
12: use PHPStan\Type\BooleanType;
13: use PHPStan\Type\CompoundType;
14: use PHPStan\Type\Constant\ConstantArrayType;
15: use PHPStan\Type\Constant\ConstantIntegerType;
16: use PHPStan\Type\ErrorType;
17: use PHPStan\Type\FloatType;
18: use PHPStan\Type\GeneralizePrecision;
19: use PHPStan\Type\InstanceofDeprecated;
20: use PHPStan\Type\IntegerType;
21: use PHPStan\Type\IntersectionType;
22: use PHPStan\Type\IsSuperTypeOfResult;
23: use PHPStan\Type\MixedType;
24: use PHPStan\Type\ObjectWithoutClassType;
25: use PHPStan\Type\StringType;
26: use PHPStan\Type\Traits\MaybeCallableTypeTrait;
27: use PHPStan\Type\Traits\NonArrayTypeTrait;
28: use PHPStan\Type\Traits\NonGenericTypeTrait;
29: use PHPStan\Type\Traits\NonIterableTypeTrait;
30: use PHPStan\Type\Traits\NonObjectTypeTrait;
31: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
32: use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
33: use PHPStan\Type\Type;
34: use PHPStan\Type\TypeCombinator;
35: use PHPStan\Type\UnionType;
36: use PHPStan\Type\VerbosityLevel;
37:
38: #[InstanceofDeprecated(insteadUse: 'Type::isLiteralString()')]
39: #[ShadowedByTurboExtension(implementation: __DIR__ . '/../../../turbo-ext/src/AccessoryLiteralStringType.cpp')]
40: class AccessoryLiteralStringType implements CompoundType, AccessoryType
41: {
42:
43: use MaybeCallableTypeTrait;
44: use NonArrayTypeTrait;
45: use NonObjectTypeTrait;
46: use NonIterableTypeTrait;
47: use UndecidedComparisonCompoundTypeTrait;
48: use NonGenericTypeTrait;
49: use NonRemoveableTypeTrait;
50:
51: /** @api */
52: public function __construct()
53: {
54: }
55:
56: public function getReferencedClasses(): array
57: {
58: return [];
59: }
60:
61: public function getObjectClassNames(): array
62: {
63: return [];
64: }
65:
66: public function getObjectClassReflections(): 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 MixedType) {
79: return AcceptsResult::createNo();
80: }
81:
82: $isLiteralString = $type->isLiteralString();
83: if ($isLiteralString->yes()) {
84: return AcceptsResult::createYes();
85: }
86:
87: if ($type instanceof CompoundType) {
88: return $type->isAcceptedBy($this, $strictTypes);
89: }
90:
91: return new AcceptsResult($isLiteralString, []);
92: }
93:
94: public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
95: {
96: if ($type instanceof CompoundType) {
97: return $type->isSubTypeOf($this);
98: }
99:
100: if ($this->equals($type)) {
101: return IsSuperTypeOfResult::createYes();
102: }
103:
104: return new IsSuperTypeOfResult($type->isLiteralString(), []);
105: }
106:
107: public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult
108: {
109: if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) {
110: return $otherType->isSuperTypeOf($this);
111: }
112:
113: return new IsSuperTypeOfResult(
114: $otherType->isLiteralString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()),
115: [],
116: );
117: }
118:
119: public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult
120: {
121: return $this->isSubTypeOf($acceptingType)->toAcceptsResult();
122: }
123:
124: public function equals(Type $type): bool
125: {
126: return $type instanceof self;
127: }
128:
129: public function describe(VerbosityLevel $level): string
130: {
131: return 'literal-string';
132: }
133:
134: public function isOffsetAccessible(): TrinaryLogic
135: {
136: return TrinaryLogic::createYes();
137: }
138:
139: public function isOffsetAccessLegal(): TrinaryLogic
140: {
141: return TrinaryLogic::createYes();
142: }
143:
144: public function hasOffsetValueType(Type $offsetType): TrinaryLogic
145: {
146: return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
147: }
148:
149: public function getOffsetValueType(Type $offsetType): Type
150: {
151: if ($this->hasOffsetValueType($offsetType)->no()) {
152: return new ErrorType();
153: }
154:
155: return new StringType();
156: }
157:
158: public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
159: {
160: $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues);
161:
162: if ($stringOffset instanceof ErrorType) {
163: return $stringOffset;
164: }
165:
166: if ($valueType->isLiteralString()->yes()) {
167: return $this;
168: }
169:
170: return new StringType();
171: }
172:
173: public function setExistingOffsetValueType(Type $offsetType, Type $valueType): Type
174: {
175: return $this;
176: }
177:
178: public function unsetOffset(Type $offsetType): Type
179: {
180: return new ErrorType();
181: }
182:
183: public function toNumber(): Type
184: {
185: return new ErrorType();
186: }
187:
188: public function toBitwiseNotType(): Type
189: {
190: return new StringType();
191: }
192:
193: public function toAbsoluteNumber(): Type
194: {
195: return new ErrorType();
196: }
197:
198: public function toInteger(): Type
199: {
200: return new IntegerType();
201: }
202:
203: public function toFloat(): Type
204: {
205: return new FloatType();
206: }
207:
208: public function toString(): Type
209: {
210: return $this;
211: }
212:
213: public function toBoolean(): BooleanType
214: {
215: return new BooleanType();
216: }
217:
218: public function toArray(): Type
219: {
220: return new ConstantArrayType(
221: [new ConstantIntegerType(0)],
222: [$this],
223: [1],
224: isList: TrinaryLogic::createYes(),
225: );
226: }
227:
228: public function toArrayKey(): Type
229: {
230: return $this;
231: }
232:
233: public function toCoercedArgumentType(bool $strictTypes): Type
234: {
235: if (!$strictTypes) {
236: return TypeCombinator::union($this->toInteger(), $this->toFloat(), $this, $this->toBoolean());
237: }
238:
239: return $this;
240: }
241:
242: public function isNull(): TrinaryLogic
243: {
244: return TrinaryLogic::createNo();
245: }
246:
247: public function isConstantValue(): TrinaryLogic
248: {
249: return TrinaryLogic::createMaybe();
250: }
251:
252: public function isConstantScalarValue(): TrinaryLogic
253: {
254: return TrinaryLogic::createMaybe();
255: }
256:
257: public function getConstantScalarTypes(): array
258: {
259: return [];
260: }
261:
262: public function getConstantScalarValues(): array
263: {
264: return [];
265: }
266:
267: public function isTrue(): TrinaryLogic
268: {
269: return TrinaryLogic::createNo();
270: }
271:
272: public function isFalse(): TrinaryLogic
273: {
274: return TrinaryLogic::createNo();
275: }
276:
277: public function isBoolean(): TrinaryLogic
278: {
279: return TrinaryLogic::createNo();
280: }
281:
282: public function isFloat(): TrinaryLogic
283: {
284: return TrinaryLogic::createNo();
285: }
286:
287: public function isInteger(): TrinaryLogic
288: {
289: return TrinaryLogic::createNo();
290: }
291:
292: public function isString(): TrinaryLogic
293: {
294: return TrinaryLogic::createYes();
295: }
296:
297: public function isNumericString(): TrinaryLogic
298: {
299: return TrinaryLogic::createMaybe();
300: }
301:
302: public function isDecimalIntegerString(): TrinaryLogic
303: {
304: return TrinaryLogic::createMaybe();
305: }
306:
307: public function isNonEmptyString(): TrinaryLogic
308: {
309: return TrinaryLogic::createMaybe();
310: }
311:
312: public function isNonFalsyString(): TrinaryLogic
313: {
314: return TrinaryLogic::createMaybe();
315: }
316:
317: public function isLiteralString(): TrinaryLogic
318: {
319: return TrinaryLogic::createYes();
320: }
321:
322: public function isLowercaseString(): TrinaryLogic
323: {
324: return TrinaryLogic::createMaybe();
325: }
326:
327: public function isClassString(): TrinaryLogic
328: {
329: return TrinaryLogic::createMaybe();
330: }
331:
332: public function isUppercaseString(): TrinaryLogic
333: {
334: return TrinaryLogic::createMaybe();
335: }
336:
337: public function getClassStringObjectType(): Type
338: {
339: return new ObjectWithoutClassType();
340: }
341:
342: public function getObjectTypeOrClassStringObjectType(): Type
343: {
344: return new ObjectWithoutClassType();
345: }
346:
347: public function hasMethod(string $methodName): TrinaryLogic
348: {
349: return TrinaryLogic::createMaybe();
350: }
351:
352: public function isVoid(): TrinaryLogic
353: {
354: return TrinaryLogic::createNo();
355: }
356:
357: public function isScalar(): TrinaryLogic
358: {
359: return TrinaryLogic::createYes();
360: }
361:
362: public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
363: {
364: return new BooleanType();
365: }
366:
367: public function traverse(callable $cb): Type
368: {
369: return $this;
370: }
371:
372: public function traverseSimultaneously(Type $right, callable $cb): Type
373: {
374: return $this;
375: }
376:
377: public function generalize(GeneralizePrecision $precision): Type
378: {
379: return new StringType();
380: }
381:
382: public function exponentiate(Type $exponent): Type
383: {
384: return new BenevolentUnionType([
385: new FloatType(),
386: new IntegerType(),
387: ]);
388: }
389:
390: public function getFiniteTypes(): array
391: {
392: return [];
393: }
394:
395: public function getDefaultBaseType(): Type
396: {
397: return new StringType();
398: }
399:
400: public function toPhpDocNode(): TypeNode
401: {
402: return new IdentifierTypeNode('literal-string');
403: }
404:
405: public function hasTemplateOrLateResolvableType(): bool
406: {
407: return false;
408: }
409:
410: }
411: