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