Skip to content

Commit 173651d

Browse files
allowComparingOnlyComparableTypes: add support for BcMath\Number
1 parent 92a6ef2 commit 173651d

3 files changed

Lines changed: 34 additions & 17 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ Few rules are enabled, but do nothing unless configured, those are marked with `
5656
## Rules:
5757

5858
### allowComparingOnlyComparableTypes
59-
- Denies using comparison operators `>,<,<=,>=,<=>` over anything other than `int|string|float|DateTimeInterface` or same size tuples containing comparable types. Null is not allowed.
60-
- Mixing different types in those operators is also forbidden, only exception is comparing floats with integers
59+
- Denies using comparison operators `>,<,<=,>=,<=>` over anything other than `int|string|float|DateTimeInterface|BcMath\Number` or same size tuples containing comparable types. Null is not allowed.
60+
- Mixing different types in those operators is also forbidden, only exception is comparing floats with integers and integers with `BcMath\Number`
6161
- Mainly targets to accidental comparisons of objects, enums or arrays which is valid in PHP, but very tricky
6262

6363
```php

src/Rule/AllowComparingOnlyComparableTypesRule.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function processNode(
6060
$rightTypeDescribed = $rightType->describe($rightType->isArray()->no() ? VerbosityLevel::typeOnly() : VerbosityLevel::value());
6161

6262
if (!$this->isComparable($leftType) || !$this->isComparable($rightType)) {
63-
$error = RuleErrorBuilder::message("Comparison {$leftTypeDescribed} {$node->getOperatorSigil()} {$rightTypeDescribed} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.")
63+
$error = RuleErrorBuilder::message("Comparison {$leftTypeDescribed} {$node->getOperatorSigil()} {$rightTypeDescribed} contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.")
6464
->identifier('shipmonk.comparingNonComparableTypes')
6565
->build();
6666
return [$error];
@@ -82,8 +82,9 @@ private function isComparable(Type $type): bool
8282
$floatType = new FloatType();
8383
$stringType = new StringType();
8484
$dateTimeType = new ObjectType(DateTimeInterface::class);
85+
$bcMathNumberType = new ObjectType('BcMath\Number');
8586

86-
if ($this->containsOnlyTypes($type, [$intType, $floatType, $stringType, $dateTimeType])) {
87+
if ($this->containsOnlyTypes($type, [$intType, $floatType, $stringType, $dateTimeType, $bcMathNumberType])) {
8788
return true;
8889
}
8990

@@ -111,11 +112,16 @@ private function isComparableTogether(
111112
$floatType = new FloatType();
112113
$stringType = new StringType();
113114
$dateTimeType = new ObjectType(DateTimeInterface::class);
115+
$bcMathNumberType = new ObjectType('BcMath\Number');
114116

115117
if ($this->containsOnlyTypes($leftType, [$intType, $floatType])) {
116118
return $this->containsOnlyTypes($rightType, [$intType, $floatType]);
117119
}
118120

121+
if ($this->containsOnlyTypes($leftType, [$intType, $bcMathNumberType])) {
122+
return $this->containsOnlyTypes($rightType, [$intType, $bcMathNumberType]);
123+
}
124+
119125
if ($this->containsOnlyTypes($leftType, [$stringType])) {
120126
return $this->containsOnlyTypes($rightType, [$stringType]);
121127
}

tests/Rule/data/AllowComparingOnlyComparableTypesRule/code.php

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace AllowComparingOnlyComparableTypesRule;
44

5+
use BcMath\Number;
56
use DateTime;
67
use DateTimeImmutable;
78

@@ -19,6 +20,7 @@ interface Bar {}
1920
Foo&Bar $fooAndBar,
2021
DateTime $dateTime,
2122
DateTimeImmutable $dateTimeImmutable,
23+
Number $number,
2224
string $string,
2325
int $int,
2426
?int $nullableInt,
@@ -27,37 +29,46 @@ interface Bar {}
2729
bool $bool,
2830
$mixed,
2931
) {
30-
$foos > $foo; // error: Comparison array > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
31-
$nullableInt > $int; // error: Comparison int|null > int contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
32-
null > $int; // error: Comparison null > int contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
33-
$foo > $foo2; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
34-
$foo > $fooOrBar; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Bar|AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
35-
$foo > $fooAndBar; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Bar&AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
32+
$foos > $foo; // error: Comparison array > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
33+
$nullableInt > $int; // error: Comparison int|null > int contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
34+
null > $int; // error: Comparison null > int contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
35+
$foo > $foo2; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
36+
$foo > $fooOrBar; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Bar|AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
37+
$foo > $fooAndBar; // error: Comparison AllowComparingOnlyComparableTypesRule\Foo > AllowComparingOnlyComparableTypesRule\Bar&AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
3638
$string > 'foo';
3739
$int > 2;
3840
$float > 2;
3941
$int > $intOrFloat;
4042
$string > $intOrFloat; // error: Cannot compare different types in string > float|int.
41-
$bool > true; // error: Comparison bool > true contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
43+
$bool > true; // error: Comparison bool > true contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
4244
$dateTime > $dateTimeImmutable;
43-
$dateTime > $foo; // error: Comparison DateTime > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
45+
$dateTime > $foo; // error: Comparison DateTime > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
4446

4547
$string > $int; // error: Cannot compare different types in string > int.
4648
$float > $int;
4749
$dateTime > $string; // error: Cannot compare different types in DateTime > string.
50+
$number > $int;
51+
$number > $float; // error: Cannot compare different types in BcMath\Number > float.
52+
$number > $string; // error: Cannot compare different types in BcMath\Number > string.
53+
$number > $intOrFloat; // error: Cannot compare different types in BcMath\Number > float|int.
54+
$number > $foo; // error: Comparison BcMath\Number > AllowComparingOnlyComparableTypesRule\Foo contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
55+
$number > $nullableInt; // error: Comparison BcMath\Number > int|null contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
4856

4957
[$int, $string] > [$int, $string];
5058
[[$int]] > [[$int]];
5159
[$int, $float, $intOrFloat, $intOrFloat] > [$int, $int, $int, $float];
52-
[$int, $string] > $foos; // error: Comparison array{int, string} > array contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
60+
[$number] > [$number];
61+
[$number] > [$int];
62+
[$number] > [$string]; // error: Cannot compare different types in array{BcMath\Number} > array{string}.
63+
[$int, $string] > $foos; // error: Comparison array{int, string} > array contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
5364
[$int] > [$int, $int]; // error: Cannot compare different types in array{int} > array{int, int}.
5465
[$int, $string] > [$int]; // error: Cannot compare different types in array{int, string} > array{int}.
5566
[$string, $int] > [$int, $string]; // error: Cannot compare different types in array{string, int} > array{int, string}.
56-
[$foo] > [$foo]; // error: Comparison array{AllowComparingOnlyComparableTypesRule\Foo} > array{AllowComparingOnlyComparableTypesRule\Foo} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
57-
[$int] > [$mixed]; // error: Comparison array{int} > array{mixed} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
67+
[$foo] > [$foo]; // error: Comparison array{AllowComparingOnlyComparableTypesRule\Foo} > array{AllowComparingOnlyComparableTypesRule\Foo} contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
68+
[$int] > [$mixed]; // error: Comparison array{int} > array{mixed} contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
5869
[$dateTime] > [[$dateTimeImmutable]]; // error: Cannot compare different types in array{DateTime} > array{array{DateTimeImmutable}}.
5970

6071
[0 => $int, 1 => $string] > [$int, $string];
61-
[1 => $int, 0 => $string] > [$int, $string]; // error: Comparison array{1: int, 0: string} > array{int, string} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
62-
['X' => $int, 'Y' => $string] > ['X' => $int, 'Y' => $string]; // error: Comparison array{X: int, Y: string} > array{X: int, Y: string} contains non-comparable type, only int|float|string|DateTimeInterface or comparable tuple is allowed.
72+
[1 => $int, 0 => $string] > [$int, $string]; // error: Comparison array{1: int, 0: string} > array{int, string} contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
73+
['X' => $int, 'Y' => $string] > ['X' => $int, 'Y' => $string]; // error: Comparison array{X: int, Y: string} > array{X: int, Y: string} contains non-comparable type, only int|float|string|DateTimeInterface|BcMath\Number or comparable tuple is allowed.
6374
};

0 commit comments

Comments
 (0)