1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Type;
4:
5: use PHPStan\TrinaryLogic;
6: use PHPStan\Type\Constant\ConstantArrayType;
7: use PHPStan\Type\Constant\ConstantBooleanType;
8: use PHPStan\Type\Constant\ConstantFloatType;
9: use PHPStan\Type\Constant\ConstantIntegerType;
10: use PHPStan\Type\Constant\ConstantStringType;
11: use PHPStan\Type\Traits\FalseyBooleanTypeTrait;
12: use PHPStan\Type\Traits\NonArrayTypeTrait;
13: use PHPStan\Type\Traits\NonCallableTypeTrait;
14: use PHPStan\Type\Traits\NonGenericTypeTrait;
15: use PHPStan\Type\Traits\NonIterableTypeTrait;
16: use PHPStan\Type\Traits\NonObjectTypeTrait;
17: use PHPStan\Type\Traits\NonRemoveableTypeTrait;
18:
19: /** @api */
20: class NullType implements ConstantScalarType
21: {
22:
23: use NonArrayTypeTrait;
24: use NonCallableTypeTrait;
25: use NonIterableTypeTrait;
26: use NonObjectTypeTrait;
27: use FalseyBooleanTypeTrait;
28: use NonGenericTypeTrait;
29: use NonRemoveableTypeTrait;
30:
31: /** @api */
32: public function __construct()
33: {
34: }
35:
36: /**
37: * @return string[]
38: */
39: public function getReferencedClasses(): array
40: {
41: return [];
42: }
43:
44: public function getConstantStrings(): array
45: {
46: return [];
47: }
48:
49: /**
50: * @return null
51: */
52: public function getValue()
53: {
54: return null;
55: }
56:
57: public function generalize(GeneralizePrecision $precision): Type
58: {
59: return $this;
60: }
61:
62: public function accepts(Type $type, bool $strictTypes): TrinaryLogic
63: {
64: if ($type instanceof self) {
65: return TrinaryLogic::createYes();
66: }
67:
68: if ($type instanceof CompoundType) {
69: return $type->isAcceptedBy($this, $strictTypes);
70: }
71:
72: return TrinaryLogic::createNo();
73: }
74:
75: public function isSuperTypeOf(Type $type): TrinaryLogic
76: {
77: if ($type instanceof self) {
78: return TrinaryLogic::createYes();
79: }
80:
81: if ($type instanceof CompoundType) {
82: return $type->isSubTypeOf($this);
83: }
84:
85: return TrinaryLogic::createNo();
86: }
87:
88: public function equals(Type $type): bool
89: {
90: return $type instanceof self;
91: }
92:
93: public function isSmallerThan(Type $otherType): TrinaryLogic
94: {
95: if ($otherType instanceof ConstantScalarType) {
96: return TrinaryLogic::createFromBoolean(null < $otherType->getValue());
97: }
98:
99: if ($otherType instanceof CompoundType) {
100: return $otherType->isGreaterThan($this);
101: }
102:
103: return TrinaryLogic::createMaybe();
104: }
105:
106: public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic
107: {
108: if ($otherType instanceof ConstantScalarType) {
109: return TrinaryLogic::createFromBoolean(null <= $otherType->getValue());
110: }
111:
112: if ($otherType instanceof CompoundType) {
113: return $otherType->isGreaterThanOrEqual($this);
114: }
115:
116: return TrinaryLogic::createMaybe();
117: }
118:
119: public function describe(VerbosityLevel $level): string
120: {
121: return 'null';
122: }
123:
124: public function toNumber(): Type
125: {
126: return new ConstantIntegerType(0);
127: }
128:
129: public function toString(): Type
130: {
131: return new ConstantStringType('');
132: }
133:
134: public function toInteger(): Type
135: {
136: return $this->toNumber();
137: }
138:
139: public function toFloat(): Type
140: {
141: return $this->toNumber()->toFloat();
142: }
143:
144: public function toArray(): Type
145: {
146: return new ConstantArrayType([], []);
147: }
148:
149: public function toArrayKey(): Type
150: {
151: return new ConstantStringType('');
152: }
153:
154: public function isOffsetAccessible(): TrinaryLogic
155: {
156: return TrinaryLogic::createYes();
157: }
158:
159: public function hasOffsetValueType(Type $offsetType): TrinaryLogic
160: {
161: return TrinaryLogic::createNo();
162: }
163:
164: public function getOffsetValueType(Type $offsetType): Type
165: {
166: return new ErrorType();
167: }
168:
169: public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
170: {
171: $array = new ConstantArrayType([], []);
172: return $array->setOffsetValueType($offsetType, $valueType, $unionValues);
173: }
174:
175: public function unsetOffset(Type $offsetType): Type
176: {
177: return $this;
178: }
179:
180: public function traverse(callable $cb): Type
181: {
182: return $this;
183: }
184:
185: public function isNull(): TrinaryLogic
186: {
187: return TrinaryLogic::createYes();
188: }
189:
190: public function isTrue(): TrinaryLogic
191: {
192: return TrinaryLogic::createNo();
193: }
194:
195: public function isFalse(): TrinaryLogic
196: {
197: return TrinaryLogic::createNo();
198: }
199:
200: public function isBoolean(): TrinaryLogic
201: {
202: return TrinaryLogic::createNo();
203: }
204:
205: public function isFloat(): TrinaryLogic
206: {
207: return TrinaryLogic::createNo();
208: }
209:
210: public function isInteger(): TrinaryLogic
211: {
212: return TrinaryLogic::createNo();
213: }
214:
215: public function isString(): TrinaryLogic
216: {
217: return TrinaryLogic::createNo();
218: }
219:
220: public function isNumericString(): TrinaryLogic
221: {
222: return TrinaryLogic::createNo();
223: }
224:
225: public function isNonEmptyString(): TrinaryLogic
226: {
227: return TrinaryLogic::createNo();
228: }
229:
230: public function isNonFalsyString(): TrinaryLogic
231: {
232: return TrinaryLogic::createNo();
233: }
234:
235: public function isLiteralString(): TrinaryLogic
236: {
237: return TrinaryLogic::createNo();
238: }
239:
240: public function isClassStringType(): TrinaryLogic
241: {
242: return TrinaryLogic::createNo();
243: }
244:
245: public function isVoid(): TrinaryLogic
246: {
247: return TrinaryLogic::createNo();
248: }
249:
250: public function isScalar(): TrinaryLogic
251: {
252: return TrinaryLogic::createNo();
253: }
254:
255: public function getSmallerType(): Type
256: {
257: return new NeverType();
258: }
259:
260: public function getSmallerOrEqualType(): Type
261: {
262: // All falsey types except '0'
263: return new UnionType([
264: new NullType(),
265: new ConstantBooleanType(false),
266: new ConstantIntegerType(0),
267: new ConstantFloatType(0.0),
268: new ConstantStringType(''),
269: new ConstantArrayType([], []),
270: ]);
271: }
272:
273: public function getGreaterType(): Type
274: {
275: // All truthy types, but also '0'
276: return new MixedType(false, new UnionType([
277: new NullType(),
278: new ConstantBooleanType(false),
279: new ConstantIntegerType(0),
280: new ConstantFloatType(0.0),
281: new ConstantStringType(''),
282: new ConstantArrayType([], []),
283: ]));
284: }
285:
286: public function getGreaterOrEqualType(): Type
287: {
288: return new MixedType();
289: }
290:
291: /**
292: * @param mixed[] $properties
293: */
294: public static function __set_state(array $properties): Type
295: {
296: return new self();
297: }
298:
299: }
300: