Skip to content

Commit 377e49c

Browse files
jlherrenondrejmirtes
authored andcommitted
Split getSmallerType()/getGreaterType() into two methods each
1 parent b7bf0c9 commit 377e49c

File tree

10 files changed

+274
-108
lines changed

10 files changed

+274
-108
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,41 @@ public function specifyTypesInCondition(
458458

459459
if ($context->truthy()) {
460460
if (!$expr->left instanceof Node\Scalar) {
461-
$result = $result->unionWith($this->create($expr->left, $rightType->getSmallerType($orEqual), TypeSpecifierContext::createTruthy()));
461+
$result = $result->unionWith(
462+
$this->create(
463+
$expr->left,
464+
$orEqual ? $rightType->getSmallerOrEqualType() : $rightType->getSmallerType(),
465+
TypeSpecifierContext::createTruthy()
466+
)
467+
);
462468
}
463469
if (!$expr->right instanceof Node\Scalar) {
464-
$result = $result->unionWith($this->create($expr->right, $leftType->getGreaterType($orEqual), TypeSpecifierContext::createTruthy()));
470+
$result = $result->unionWith(
471+
$this->create(
472+
$expr->right,
473+
$orEqual ? $leftType->getGreaterOrEqualType() : $leftType->getGreaterType(),
474+
TypeSpecifierContext::createTruthy()
475+
)
476+
);
465477
}
466478
} elseif ($context->falsey()) {
467479
if (!$expr->left instanceof Node\Scalar) {
468-
$result = $result->unionWith($this->create($expr->left, $rightType->getGreaterType(!$orEqual), TypeSpecifierContext::createTruthy()));
480+
$result = $result->unionWith(
481+
$this->create(
482+
$expr->left,
483+
$orEqual ? $rightType->getGreaterType() : $rightType->getGreaterOrEqualType(),
484+
TypeSpecifierContext::createTruthy()
485+
)
486+
);
469487
}
470488
if (!$expr->right instanceof Node\Scalar) {
471-
$result = $result->unionWith($this->create($expr->right, $leftType->getSmallerType(!$orEqual), TypeSpecifierContext::createTruthy()));
489+
$result = $result->unionWith(
490+
$this->create(
491+
$expr->right,
492+
$orEqual ? $leftType->getSmallerType() : $leftType->getSmallerOrEqualType(),
493+
TypeSpecifierContext::createTruthy()
494+
)
495+
);
472496
}
473497
}
474498

src/Type/Constant/ConstantBooleanType.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,38 +33,38 @@ public function describe(VerbosityLevel $level): string
3333
return $this->value ? 'true' : 'false';
3434
}
3535

36-
public function getSmallerType(bool $orEqual = false): Type
36+
public function getSmallerType(): Type
3737
{
38-
if ($orEqual) {
39-
if ($this->value) {
40-
return new MixedType();
41-
}
42-
return StaticTypeFactory::falsey();
43-
}
44-
4538
if ($this->value) {
4639
return StaticTypeFactory::falsey();
4740
}
48-
4941
return new NeverType();
5042
}
5143

52-
public function getGreaterType(bool $orEqual = false): Type
44+
public function getSmallerOrEqualType(): Type
5345
{
54-
if ($orEqual) {
55-
if ($this->value) {
56-
return StaticTypeFactory::truthy();
57-
}
46+
if ($this->value) {
5847
return new MixedType();
5948
}
49+
return StaticTypeFactory::falsey();
50+
}
6051

52+
public function getGreaterType(): Type
53+
{
6154
if ($this->value) {
6255
return new NeverType();
6356
}
64-
6557
return StaticTypeFactory::truthy();
6658
}
6759

60+
public function getGreaterOrEqualType(): Type
61+
{
62+
if ($this->value) {
63+
return StaticTypeFactory::truthy();
64+
}
65+
return new MixedType();
66+
}
67+
6868
public function toBoolean(): BooleanType
6969
{
7070
return $this;

src/Type/Constant/ConstantStringType.php

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -302,45 +302,65 @@ public function generalize(): Type
302302
return new StringType();
303303
}
304304

305-
public function getSmallerType(bool $orEqual = false): Type
305+
public function getSmallerType(): Type
306306
{
307307
$subtractedTypes = [
308-
IntegerRangeType::createAllGreaterThan((float) $this->value, !$orEqual),
308+
new ConstantBooleanType(true),
309+
IntegerRangeType::createAllGreaterThanOrEqualTo((float) $this->value),
309310
];
310311

311-
if ($this->value === '' && !$orEqual) {
312+
if ($this->value === '') {
312313
$subtractedTypes[] = new NullType();
313314
$subtractedTypes[] = new StringType();
314315
}
315316

316-
$boolValue = (bool) $this->value;
317-
if (!$boolValue && !$orEqual) {
317+
if (!(bool) $this->value) {
318318
$subtractedTypes[] = new ConstantBooleanType(false);
319319
}
320-
if (!$boolValue || !$orEqual) {
320+
321+
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
322+
}
323+
324+
public function getSmallerOrEqualType(): Type
325+
{
326+
$subtractedTypes = [
327+
IntegerRangeType::createAllGreaterThan((float) $this->value),
328+
];
329+
330+
if (!(bool) $this->value) {
321331
$subtractedTypes[] = new ConstantBooleanType(true);
322332
}
323333

324334
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
325335
}
326336

327-
public function getGreaterType(bool $orEqual = false): Type
337+
public function getGreaterType(): Type
328338
{
329339
$subtractedTypes = [
330-
IntegerRangeType::createAllSmallerThan((float) $this->value, !$orEqual),
340+
new ConstantBooleanType(false),
341+
IntegerRangeType::createAllSmallerThanOrEqualTo((float) $this->value),
331342
];
332343

333-
$boolValue = (bool) $this->value;
334-
if ($boolValue || !$orEqual) {
335-
$subtractedTypes[] = new ConstantBooleanType(false);
336-
}
337-
if ($boolValue && !$orEqual) {
344+
if ((bool) $this->value) {
338345
$subtractedTypes[] = new ConstantBooleanType(true);
339346
}
340347

341348
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
342349
}
343350

351+
public function getGreaterOrEqualType(): Type
352+
{
353+
$subtractedTypes = [
354+
IntegerRangeType::createAllSmallerThan((float) $this->value),
355+
];
356+
357+
if ((bool) $this->value) {
358+
$subtractedTypes[] = new ConstantBooleanType(false);
359+
}
360+
361+
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
362+
}
363+
344364
/**
345365
* @param mixed[] $properties
346366
* @return Type

src/Type/IntegerRangeType.php

Lines changed: 87 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,61 +48,97 @@ protected static function isDisjoint(?int $minA, ?int $maxA, ?int $minB, ?int $m
4848
}
4949

5050
/**
51-
* Return the range of integers smaller than (or equal to) the given value
51+
* Return the range of integers smaller than the given value
5252
*
5353
* @param int|float $value
54-
* @param bool $orEqual
5554
* @return Type
5655
*/
57-
public static function createAllSmallerThan($value, bool $orEqual = false): Type
56+
public static function createAllSmallerThan($value): Type
5857
{
5958
if (is_int($value)) {
60-
return self::fromInterval(null, $value, $orEqual ? 0 : -1);
59+
return self::fromInterval(null, $value, -1);
6160
}
6261

63-
if ($value > PHP_INT_MAX || $value >= PHP_INT_MAX && $orEqual) {
62+
if ($value > PHP_INT_MAX) {
6463
return new IntegerType();
6564
}
6665

67-
if ($value < PHP_INT_MIN || $value <= PHP_INT_MIN && !$orEqual) {
66+
if ($value <= PHP_INT_MIN) {
6867
return new NeverType();
6968
}
7069

71-
if ($orEqual) {
72-
return self::fromInterval(null, (int) floor($value));
73-
}
74-
7570
return self::fromInterval(null, (int) ceil($value), -1);
7671
}
7772

7873
/**
79-
* Return the range of integers greater than (or equal to) the given value
74+
* Return the range of integers smaller than or equal to the given value
8075
*
8176
* @param int|float $value
82-
* @param bool $orEqual
8377
* @return Type
8478
*/
85-
public static function createAllGreaterThan($value, bool $orEqual = false): Type
79+
public static function createAllSmallerThanOrEqualTo($value): Type
8680
{
8781
if (is_int($value)) {
88-
return self::fromInterval($value, null, $orEqual ? 0 : 1);
82+
return self::fromInterval(null, $value);
8983
}
9084

91-
if ($value < PHP_INT_MIN || $value <= PHP_INT_MIN && $orEqual) {
85+
if ($value >= PHP_INT_MAX) {
9286
return new IntegerType();
9387
}
9488

95-
if ($value > PHP_INT_MAX || $value >= PHP_INT_MAX && !$orEqual) {
89+
if ($value < PHP_INT_MIN) {
9690
return new NeverType();
9791
}
9892

99-
if ($orEqual) {
100-
return self::fromInterval((int) ceil($value), null);
93+
return self::fromInterval(null, (int) floor($value));
94+
}
95+
96+
/**
97+
* Return the range of integers greater than the given value
98+
*
99+
* @param int|float $value
100+
* @return Type
101+
*/
102+
public static function createAllGreaterThan($value): Type
103+
{
104+
if (is_int($value)) {
105+
return self::fromInterval($value, null, 1);
106+
}
107+
108+
if ($value < PHP_INT_MIN) {
109+
return new IntegerType();
110+
}
111+
112+
if ($value >= PHP_INT_MAX) {
113+
return new NeverType();
101114
}
102115

103116
return self::fromInterval((int) floor($value), null, 1);
104117
}
105118

119+
/**
120+
* Return the range of integers greater than or equal to the given value
121+
*
122+
* @param int|float $value
123+
* @return Type
124+
*/
125+
public static function createAllGreaterThanOrEqualTo($value): Type
126+
{
127+
if (is_int($value)) {
128+
return self::fromInterval($value, null);
129+
}
130+
131+
if ($value <= PHP_INT_MIN) {
132+
return new IntegerType();
133+
}
134+
135+
if ($value > PHP_INT_MAX) {
136+
return new NeverType();
137+
}
138+
139+
return self::fromInterval((int) ceil($value), null);
140+
}
141+
106142
public function getMin(): ?int
107143
{
108144
return $this->min;
@@ -269,40 +305,61 @@ public function isGreaterThan(Type $otherType, bool $orEqual = false): TrinaryLo
269305
return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller);
270306
}
271307

272-
public function getSmallerType(bool $orEqual = false): Type
308+
public function getSmallerType(): Type
309+
{
310+
$subtractedTypes = [
311+
new ConstantBooleanType(true),
312+
];
313+
314+
if ($this->max !== null) {
315+
$subtractedTypes[] = self::createAllGreaterThanOrEqualTo($this->max);
316+
}
317+
318+
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
319+
}
320+
321+
public function getSmallerOrEqualType(): Type
273322
{
274323
$subtractedTypes = [];
275324

276325
if ($this->max !== null) {
277-
$subtractedTypes[] = self::createAllGreaterThan($this->max, !$orEqual);
326+
$subtractedTypes[] = self::createAllGreaterThan($this->max);
278327
}
279328

280-
if (!$orEqual) {
329+
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
330+
}
331+
332+
public function getGreaterType(): Type
333+
{
334+
$subtractedTypes = [
335+
new NullType(),
336+
new ConstantBooleanType(false),
337+
];
338+
339+
if ($this->min !== null) {
340+
$subtractedTypes[] = self::createAllSmallerThanOrEqualTo($this->min);
341+
}
342+
343+
if ($this->min !== null && $this->min > 0 || $this->max !== null && $this->max < 0) {
281344
$subtractedTypes[] = new ConstantBooleanType(true);
282345
}
283346

284347
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
285348
}
286349

287-
public function getGreaterType(bool $orEqual = false): Type
350+
public function getGreaterOrEqualType(): Type
288351
{
289352
$subtractedTypes = [];
290353

291354
if ($this->min !== null) {
292-
$subtractedTypes[] = self::createAllSmallerThan($this->min, !$orEqual);
355+
$subtractedTypes[] = self::createAllSmallerThan($this->min);
293356
}
294357

295-
$alwaysTruthy = $this->min !== null && $this->min > 0 || $this->max !== null && $this->max < 0;
296-
297-
if ($alwaysTruthy || !$orEqual) {
358+
if ($this->min !== null && $this->min > 0 || $this->max !== null && $this->max < 0) {
298359
$subtractedTypes[] = new NullType();
299360
$subtractedTypes[] = new ConstantBooleanType(false);
300361
}
301362

302-
if ($alwaysTruthy && !$orEqual) {
303-
$subtractedTypes[] = new ConstantBooleanType(true);
304-
}
305-
306363
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
307364
}
308365

0 commit comments

Comments
 (0)