Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/Rules/Operators/OperatorRuleHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -68,7 +73,13 @@ public function isValidForDecrement(Scope $scope, Expr $expr): bool

private function isSubtypeOfNumber(Scope $scope, Expr $expr): bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is also used by isValidForArithmeticOperation so you have more impact than expected for instance it changes the behavior of the rule with

// Addition or Substraction
$a = BcMath\Number + BcMath\Number
$a = int - BcMath\Number

// Unary
$a = - BcMath\Number

// Division, Exponentiation, Modulo, Multiplication
...

I recommend you to add test for those case, and I'm not sure they should stop reporting error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I added more tests based on the existing operators.php test file. Looks like there were no issues with BcMath\Number before... I'm not sure why

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that this is maybe safer to handle the special case directly inside isValidForIncrement and isValidForDecrement rather than inside isSubtypeOfNumber.

As an exemple isValidForIncrement has a special case

if ($type->isString()->yes()) {
			// Because `$a = 'a'; $a++;` is valid
			return true;
		}

{
$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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before supporting an union here, you might want to support an union on PHPStan side, cf
https://phpstan.org/r/3e185620-55d1-470c-ba3a-c7ae8dc603fd


$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -18,6 +19,7 @@ protected function getRule(): Rule
return $this->createRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -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
*/
Expand All @@ -37,4 +47,9 @@ abstract protected function createRule(OperatorRuleHelper $helper): Rule;
*/
abstract protected function getExpectedErrors(): array;

/**
* @return list<array{0: string, 1: int, 2?: string}>
*/
abstract protected function getExpectedErrorsWithBcMath(): array;

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ protected function getExpectedErrors(): array
];
}

/**
* {@inheritdoc}
*/
protected function getExpectedErrorsWithBcMath(): array
{
return [];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ protected function getExpectedErrors(): array
];
}

/**
* {@inheritdoc}
*/
protected function getExpectedErrorsWithBcMath(): array
{
return [];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ protected function getExpectedErrors(): array
];
}

/**
* {@inheritdoc}
*/
protected function getExpectedErrorsWithBcMath(): array
{
return [];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ protected function getExpectedErrors(): array
];
}

/**
* {@inheritdoc}
*/
protected function getExpectedErrorsWithBcMath(): array
{
return [];
}

}
10 changes: 10 additions & 0 deletions tests/Rules/Operators/OperandInArithmeticUnaryMinusRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -17,6 +18,7 @@ protected function getRule(): Rule
return new OperandInArithmeticUnaryMinusRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -31,4 +33,12 @@ public function testRule(): void
]);
}

/**
* @requires PHP >= 8.4
*/
public function testRuleWithBcMath(): void
{
$this->analyse([__DIR__ . '/data/operators-bcmath.php'], []);
}

}
10 changes: 10 additions & 0 deletions tests/Rules/Operators/OperandInArithmeticUnaryPlusRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -17,6 +18,7 @@ protected function getRule(): Rule
return new OperandInArithmeticUnaryPlusRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -31,4 +33,12 @@ public function testRule(): void
]);
}

/**
* @requires PHP >= 8.4
*/
public function testRuleWithBcMath(): void
{
$this->analyse([__DIR__ . '/data/operators-bcmath.php'], []);
}

}
23 changes: 23 additions & 0 deletions tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -19,6 +20,7 @@ protected function getRule(): Rule
return new OperandsInArithmeticAdditionRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand Down Expand Up @@ -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,
],
]);
}

}
23 changes: 23 additions & 0 deletions tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -17,6 +18,7 @@ protected function getRule(): Rule
return new OperandsInArithmeticDivisionRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -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,
],
]);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -17,6 +18,7 @@ protected function getRule(): Rule
return new OperandsInArithmeticExponentiationRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -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,
],
]);
}

}
23 changes: 23 additions & 0 deletions tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Operators;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -17,6 +18,7 @@ protected function getRule(): Rule
return new OperandsInArithmeticModuloRule(
new OperatorRuleHelper(
self::getContainer()->getByType(RuleLevelHelper::class),
self::getContainer()->getByType(PhpVersion::class),
),
);
}
Expand All @@ -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,
],
]);
}

}
Loading