diff --git a/src/Rules/Operators/OperatorRuleHelper.php b/src/Rules/Operators/OperatorRuleHelper.php index 6de54ca..646f8ac 100644 --- a/src/Rules/Operators/OperatorRuleHelper.php +++ b/src/Rules/Operators/OperatorRuleHelper.php @@ -4,6 +4,7 @@ use PhpParser\Node\Expr; use PHPStan\Analyser\Scope; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\Accessory\AccessoryNumericStringType; use PHPStan\Type\BenevolentUnionType; @@ -12,6 +13,7 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; +use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; @@ -21,9 +23,12 @@ class OperatorRuleHelper private RuleLevelHelper $ruleLevelHelper; - public function __construct(RuleLevelHelper $ruleLevelHelper) + private PhpVersion $phpVersion; + + public function __construct(RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion) { $this->ruleLevelHelper = $ruleLevelHelper; + $this->phpVersion = $phpVersion; } public function isValidForArithmeticOperation(Scope $scope, Expr $expr): bool @@ -68,7 +73,13 @@ public function isValidForDecrement(Scope $scope, Expr $expr): bool private function isSubtypeOfNumber(Scope $scope, Expr $expr): bool { - $acceptedType = new UnionType([new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()])]); + $acceptedTypes = [new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()])]; + + if ($this->phpVersion->supportsBcMathNumberOperatorOverloading()) { + $acceptedTypes[] = new ObjectType('BcMath\Number'); + } + + $acceptedType = new UnionType($acceptedTypes); $type = $this->ruleLevelHelper->findTypeToCheck( $scope, diff --git a/tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTestCase.php b/tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTestCase.php index a1206dc..0877b94 100644 --- a/tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTestCase.php +++ b/tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTestCase.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -18,6 +19,7 @@ protected function getRule(): Rule return $this->createRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -27,6 +29,14 @@ public function testRule(): void $this->analyse([__DIR__ . '/data/increment-decrement.php'], $this->getExpectedErrors()); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/increment-decrement-bcmath.php'], $this->getExpectedErrorsWithBcMath()); + } + /** * @return T */ @@ -37,4 +47,9 @@ abstract protected function createRule(OperatorRuleHelper $helper): Rule; */ abstract protected function getExpectedErrors(): array; + /** + * @return list + */ + abstract protected function getExpectedErrorsWithBcMath(): array; + } diff --git a/tests/Rules/Operators/OperandInArithmeticPostDecrementRuleTest.php b/tests/Rules/Operators/OperandInArithmeticPostDecrementRuleTest.php index c4ea156..3869741 100644 --- a/tests/Rules/Operators/OperandInArithmeticPostDecrementRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticPostDecrementRuleTest.php @@ -44,4 +44,12 @@ protected function getExpectedErrors(): array ]; } + /** + * {@inheritdoc} + */ + protected function getExpectedErrorsWithBcMath(): array + { + return []; + } + } diff --git a/tests/Rules/Operators/OperandInArithmeticPostIncrementRuleTest.php b/tests/Rules/Operators/OperandInArithmeticPostIncrementRuleTest.php index 94357e6..353e4b7 100644 --- a/tests/Rules/Operators/OperandInArithmeticPostIncrementRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticPostIncrementRuleTest.php @@ -40,4 +40,12 @@ protected function getExpectedErrors(): array ]; } + /** + * {@inheritdoc} + */ + protected function getExpectedErrorsWithBcMath(): array + { + return []; + } + } diff --git a/tests/Rules/Operators/OperandInArithmeticPreDecrementRuleTest.php b/tests/Rules/Operators/OperandInArithmeticPreDecrementRuleTest.php index 2bb021a..d629c8e 100644 --- a/tests/Rules/Operators/OperandInArithmeticPreDecrementRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticPreDecrementRuleTest.php @@ -44,4 +44,12 @@ protected function getExpectedErrors(): array ]; } + /** + * {@inheritdoc} + */ + protected function getExpectedErrorsWithBcMath(): array + { + return []; + } + } diff --git a/tests/Rules/Operators/OperandInArithmeticPreIncrementRuleTest.php b/tests/Rules/Operators/OperandInArithmeticPreIncrementRuleTest.php index 2ffe1bb..a6a855b 100644 --- a/tests/Rules/Operators/OperandInArithmeticPreIncrementRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticPreIncrementRuleTest.php @@ -40,4 +40,12 @@ protected function getExpectedErrors(): array ]; } + /** + * {@inheritdoc} + */ + protected function getExpectedErrorsWithBcMath(): array + { + return []; + } + } diff --git a/tests/Rules/Operators/OperandInArithmeticUnaryMinusRuleTest.php b/tests/Rules/Operators/OperandInArithmeticUnaryMinusRuleTest.php index d202bdb..fbd3964 100644 --- a/tests/Rules/Operators/OperandInArithmeticUnaryMinusRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticUnaryMinusRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandInArithmeticUnaryMinusRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -31,4 +33,12 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], []); + } + } diff --git a/tests/Rules/Operators/OperandInArithmeticUnaryPlusRuleTest.php b/tests/Rules/Operators/OperandInArithmeticUnaryPlusRuleTest.php index 6cc253a..2a961f3 100644 --- a/tests/Rules/Operators/OperandInArithmeticUnaryPlusRuleTest.php +++ b/tests/Rules/Operators/OperandInArithmeticUnaryPlusRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandInArithmeticUnaryPlusRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -31,4 +33,12 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], []); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php index cc53305..568056d 100644 --- a/tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -19,6 +20,7 @@ protected function getRule(): Rule return new OperandsInArithmeticAdditionRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -60,4 +62,25 @@ public function testRule(): void $this->analyse([__DIR__ . '/data/operators.php'], $messages); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in +, null given on the right side.', + 36, + ], + [ + 'Only numeric types are allowed in +, null given on the left side.', + 37, + ], + [ + 'Only numeric types are allowed in +, null given on the right side.', + 157, + ], + ]); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php index 5714808..e5ca255 100644 --- a/tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandsInArithmeticDivisionRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -43,4 +45,25 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in /, null given on the right side.', + 96, + ], + [ + 'Only numeric types are allowed in /, null given on the left side.', + 97, + ], + [ + 'Only numeric types are allowed in /, null given on the right side.', + 217, + ], + ]); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php index 539a969..97ac2e8 100644 --- a/tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandsInArithmeticExponentiationRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -43,4 +45,25 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in **, null given on the right side.', + 116, + ], + [ + 'Only numeric types are allowed in **, null given on the left side.', + 117, + ], + [ + 'Only numeric types are allowed in **, null given on the right side.', + 237, + ], + ]); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php index 54ccc48..69ff35c 100644 --- a/tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandsInArithmeticModuloRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -43,4 +45,25 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in %, null given on the right side.', + 136, + ], + [ + 'Only numeric types are allowed in %, null given on the left side.', + 137, + ], + [ + 'Only numeric types are allowed in %, null given on the right side.', + 257, + ], + ]); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php index 4864120..89725ef 100644 --- a/tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandsInArithmeticMultiplicationRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -43,4 +45,25 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in *, null given on the right side.', + 76, + ], + [ + 'Only numeric types are allowed in *, null given on the left side.', + 77, + ], + [ + 'Only numeric types are allowed in *, null given on the right side.', + 197, + ], + ]); + } + } diff --git a/tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php b/tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php index 66dc3b0..8539b8e 100644 --- a/tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php +++ b/tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Operators; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; @@ -17,6 +18,7 @@ protected function getRule(): Rule return new OperandsInArithmeticSubtractionRule( new OperatorRuleHelper( self::getContainer()->getByType(RuleLevelHelper::class), + self::getContainer()->getByType(PhpVersion::class), ), ); } @@ -43,4 +45,25 @@ public function testRule(): void ]); } + /** + * @requires PHP >= 8.4 + */ + public function testRuleWithBcMath(): void + { + $this->analyse([__DIR__ . '/data/operators-bcmath.php'], [ + [ + 'Only numeric types are allowed in -, null given on the right side.', + 56, + ], + [ + 'Only numeric types are allowed in -, null given on the left side.', + 57, + ], + [ + 'Only numeric types are allowed in -, null given on the right side.', + 177, + ], + ]); + } + } diff --git a/tests/Rules/Operators/data/increment-decrement-bcmath.php b/tests/Rules/Operators/data/increment-decrement-bcmath.php new file mode 100644 index 0000000..55615e7 --- /dev/null +++ b/tests/Rules/Operators/data/increment-decrement-bcmath.php @@ -0,0 +1,21 @@ +