Skip to content
42 changes: 39 additions & 3 deletions src/Rules/Operators/OperatorRuleHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Rules\Operators;

use PhpParser\Node\Expr;
use PhpParser\Node\Scalar\Int_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
Expand Down Expand Up @@ -38,7 +39,20 @@ public function isValidForArithmeticOperation(Scope $scope, Expr $expr): bool
return true;
}

return $this->isSubtypeOfNumber($scope, $expr);
if ($this->isSubtypeOfNumber($scope, $expr)) {
return true;
}

// Check if the type supports arithmetic via operator overloading extensions
// (only applies to object types like GMP, BCMath\Number)
if ($type->isObject()->yes()) {
$resultType = $scope->getType(new Expr\BinaryOp\Plus($expr, new Int_(1)));
if (!$resultType instanceof ErrorType) {
return true;
}
}

return false;
}

public function isValidForIncrement(Scope $scope, Expr $expr): bool
Expand All @@ -53,7 +67,18 @@ public function isValidForIncrement(Scope $scope, Expr $expr): bool
return true;
}

return $this->isSubtypeOfNumber($scope, $expr);
if ($this->isSubtypeOfNumber($scope, $expr)) {
return true;
}

if ($type->isObject()->yes()) {
$resultType = $scope->getType(new Expr\PostInc($expr));
if (!$resultType instanceof ErrorType) {
return true;
}
}

return false;
}

public function isValidForDecrement(Scope $scope, Expr $expr): bool
Expand All @@ -63,7 +88,18 @@ public function isValidForDecrement(Scope $scope, Expr $expr): bool
return true;
}

return $this->isSubtypeOfNumber($scope, $expr);
if ($this->isSubtypeOfNumber($scope, $expr)) {
return true;
}

if ($type->isObject()->yes()) {
$resultType = $scope->getType(new Expr\PostDec($expr));
if (!$resultType instanceof ErrorType) {
return true;
}
}

return false;
}

private function isSubtypeOfNumber(Scope $scope, Expr $expr): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ protected function getExpectedErrors(): array
return [
[
'Only numeric types are allowed in post-decrement, false given.',
21,
25,
],
[
'Only numeric types are allowed in post-decrement, string given.',
22,
26,
],
[
'Only numeric types are allowed in post-decrement, null given.',
23,
27,
],
[
'Only numeric types are allowed in post-decrement, stdClass given.',
24,
28,
],
[
'Only numeric types are allowed in post-decrement, int|stdClass|string given.',
26,
30,
],
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ protected function getExpectedErrors(): array
return [
[
'Only numeric types are allowed in post-increment, false given.',
32,
38,
],
[
'Only numeric types are allowed in post-increment, null given.',
34,
40,
],
[
'Only numeric types are allowed in post-increment, stdClass given.',
35,
41,
],
[
'Only numeric types are allowed in post-increment, int|stdClass|string given.',
37,
43,
],
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ protected function getExpectedErrors(): array
return [
[
'Only numeric types are allowed in pre-decrement, false given.',
43,
51,
],
[
'Only numeric types are allowed in pre-decrement, string given.',
44,
52,
],
[
'Only numeric types are allowed in pre-decrement, null given.',
45,
53,
],
[
'Only numeric types are allowed in pre-decrement, stdClass given.',
46,
54,
],
[
'Only numeric types are allowed in pre-decrement, int|stdClass|string given.',
48,
56,
],
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ protected function getExpectedErrors(): array
return [
[
'Only numeric types are allowed in pre-increment, false given.',
54,
64,
],
[
'Only numeric types are allowed in pre-increment, null given.',
56,
66,
],
[
'Only numeric types are allowed in pre-increment, stdClass given.',
57,
67,
],
[
'Only numeric types are allowed in pre-increment, int|stdClass|string given.',
59,
69,
],
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ public function testRule(): void
$this->analyse([__DIR__ . '/data/operators.php'], $messages);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
5 changes: 5 additions & 0 deletions tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public function testRule(): void
]);
}

public function testOperatorOverloads(): void
{
$this->analyse([__DIR__ . '/data/operator-overloads.php'], []);
}

}
20 changes: 16 additions & 4 deletions tests/Rules/Operators/data/increment-decrement.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Operators;

use BcMath\Number;
use GMP;
use stdClass;

$int = 123;
Expand All @@ -14,8 +16,10 @@
$mixed = foo();
/** @var int|string|stdClass $union */
$union = bar();
$gmp = new GMP('1');
$bcmath = new BCMath\Number('2');

(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union): void {
(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union, $gmp, $bcmath): void {
$int--;
$float--;
$bool--;
Expand All @@ -24,9 +28,11 @@
$object--;
$mixed--;
$union--;
$gmp--;
$bcmath--;
})();

(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union): void {
(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union, $gmp, $bcmath): void {
$int++;
$float++;
$bool++;
Expand All @@ -35,9 +41,11 @@
$object++;
$mixed++;
$union++;
$gmp++;
$bcmath++;
})();

(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union): void {
(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union, $gmp, $bcmath): void {
--$int;
--$float;
--$bool;
Expand All @@ -46,9 +54,11 @@
--$object;
--$mixed;
--$union;
--$gmp;
--$bcmath;
})();

(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union): void {
(function () use ($int, $float, $bool, $string, $null, $object, $mixed, $union, $gmp, $bcmath): void {
++$int;
++$float;
++$bool;
Expand All @@ -57,6 +67,8 @@
++$object;
++$mixed;
++$union;
++$gmp;
++$bcmath;
})();


Expand Down
Loading
Loading