Skip to content

Commit b7dd96a

Browse files
kamil-zacekondrejmirtes
authored andcommittedFeb 21, 2023
Strict operator type check for assign operations
·
2.0.61.5.0
1 parent 66b378f commit b7dd96a

15 files changed

+317
-90
lines changed
 

‎phpstan-baseline.neon‎

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -107,61 +107,31 @@ parameters:
107107
count: 1
108108
path: src/Rules/Operators/OperandsInArithmeticAdditionRule.php
109109

110-
-
111-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticAdditionRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
112-
count: 1
113-
path: src/Rules/Operators/OperandsInArithmeticAdditionRule.php
114-
115110
-
116111
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticDivisionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
117112
count: 1
118113
path: src/Rules/Operators/OperandsInArithmeticDivisionRule.php
119114

120-
-
121-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticDivisionRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
122-
count: 1
123-
path: src/Rules/Operators/OperandsInArithmeticDivisionRule.php
124-
125115
-
126116
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticExponentiationRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
127117
count: 1
128118
path: src/Rules/Operators/OperandsInArithmeticExponentiationRule.php
129119

130-
-
131-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticExponentiationRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
132-
count: 1
133-
path: src/Rules/Operators/OperandsInArithmeticExponentiationRule.php
134-
135120
-
136121
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticModuloRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
137122
count: 1
138123
path: src/Rules/Operators/OperandsInArithmeticModuloRule.php
139124

140-
-
141-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticModuloRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
142-
count: 1
143-
path: src/Rules/Operators/OperandsInArithmeticModuloRule.php
144-
145125
-
146126
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticMultiplicationRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
147127
count: 1
148128
path: src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php
149129

150-
-
151-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticMultiplicationRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
152-
count: 1
153-
path: src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php
154-
155130
-
156131
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticSubtractionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
157132
count: 1
158133
path: src/Rules/Operators/OperandsInArithmeticSubtractionRule.php
159134

160-
-
161-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticSubtractionRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
162-
count: 1
163-
path: src/Rules/Operators/OperandsInArithmeticSubtractionRule.php
164-
165135
-
166136
message: "#^Class PHPStan\\\\Rules\\\\StrictCalls\\\\DynamicCallOnStaticMethodsRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
167137
count: 1

‎rules.neon‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,33 @@ services:
204204

205205
-
206206
class: PHPStan\Rules\Operators\OperandsInArithmeticAdditionRule
207+
arguments:
208+
bleedingEdge: %featureToggles.bleedingEdge%
207209

208210
-
209211
class: PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule
212+
arguments:
213+
bleedingEdge: %featureToggles.bleedingEdge%
210214

211215
-
212216
class: PHPStan\Rules\Operators\OperandsInArithmeticExponentiationRule
217+
arguments:
218+
bleedingEdge: %featureToggles.bleedingEdge%
213219

214220
-
215221
class: PHPStan\Rules\Operators\OperandsInArithmeticModuloRule
222+
arguments:
223+
bleedingEdge: %featureToggles.bleedingEdge%
216224

217225
-
218226
class: PHPStan\Rules\Operators\OperandsInArithmeticMultiplicationRule
227+
arguments:
228+
bleedingEdge: %featureToggles.bleedingEdge%
219229

220230
-
221231
class: PHPStan\Rules\Operators\OperandsInArithmeticSubtractionRule
232+
arguments:
233+
bleedingEdge: %featureToggles.bleedingEdge%
222234

223235
-
224236
class: PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule

‎src/Rules/Operators/OperandsInArithmeticAdditionRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Plus;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Plus as AssignOpPlus;
8+
use PhpParser\Node\Expr\BinaryOp\Plus as BinaryOpPlus;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -17,36 +18,49 @@ class OperandsInArithmeticAdditionRule implements Rule
1718
/** @var OperatorRuleHelper */
1819
private $helper;
1920

20-
public function __construct(OperatorRuleHelper $helper)
21+
/** @var bool */
22+
private $bleedingEdge;
23+
24+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2125
{
2226
$this->helper = $helper;
27+
$this->bleedingEdge = $bleedingEdge;
2328
}
2429

2530
public function getNodeType(): string
2631
{
27-
return Plus::class;
32+
return Expr::class;
2833
}
2934

3035
/**
31-
* @param BooleanAnd $node
3236
* @return string[] errors
3337
*/
3438
public function processNode(Node $node, Scope $scope): array
3539
{
36-
$leftType = $scope->getType($node->left);
37-
$rightType = $scope->getType($node->right);
40+
if ($node instanceof BinaryOpPlus) {
41+
$left = $node->left;
42+
$right = $node->right;
43+
} elseif ($node instanceof AssignOpPlus && $this->bleedingEdge) {
44+
$left = $node->var;
45+
$right = $node->expr;
46+
} else {
47+
return [];
48+
}
49+
50+
$leftType = $scope->getType($left);
51+
$rightType = $scope->getType($right);
3852
if (count($leftType->getArrays()) > 0 && count($rightType->getArrays()) > 0) {
3953
return [];
4054
}
4155

4256
$messages = [];
43-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
57+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
4458
$messages[] = sprintf(
4559
'Only numeric types are allowed in +, %s given on the left side.',
4660
$leftType->describe(VerbosityLevel::typeOnly())
4761
);
4862
}
49-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
63+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
5064
$messages[] = sprintf(
5165
'Only numeric types are allowed in +, %s given on the right side.',
5266
$rightType->describe(VerbosityLevel::typeOnly())

‎src/Rules/Operators/OperandsInArithmeticDivisionRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Div;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Div as AssignOpDiv;
8+
use PhpParser\Node\Expr\BinaryOp\Div as BinaryOpDiv;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -16,33 +17,46 @@ class OperandsInArithmeticDivisionRule implements Rule
1617
/** @var OperatorRuleHelper */
1718
private $helper;
1819

19-
public function __construct(OperatorRuleHelper $helper)
20+
/** @var bool */
21+
private $bleedingEdge;
22+
23+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2024
{
2125
$this->helper = $helper;
26+
$this->bleedingEdge = $bleedingEdge;
2227
}
2328

2429
public function getNodeType(): string
2530
{
26-
return Div::class;
31+
return Expr::class;
2732
}
2833

2934
/**
30-
* @param BooleanAnd $node
3135
* @return string[] errors
3236
*/
3337
public function processNode(Node $node, Scope $scope): array
3438
{
39+
if ($node instanceof BinaryOpDiv) {
40+
$left = $node->left;
41+
$right = $node->right;
42+
} elseif ($node instanceof AssignOpDiv && $this->bleedingEdge) {
43+
$left = $node->var;
44+
$right = $node->expr;
45+
} else {
46+
return [];
47+
}
48+
3549
$messages = [];
36-
$leftType = $scope->getType($node->left);
37-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
50+
$leftType = $scope->getType($left);
51+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
3852
$messages[] = sprintf(
3953
'Only numeric types are allowed in /, %s given on the left side.',
4054
$leftType->describe(VerbosityLevel::typeOnly())
4155
);
4256
}
4357

44-
$rightType = $scope->getType($node->right);
45-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
58+
$rightType = $scope->getType($right);
59+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
4660
$messages[] = sprintf(
4761
'Only numeric types are allowed in /, %s given on the right side.',
4862
$rightType->describe(VerbosityLevel::typeOnly())

‎src/Rules/Operators/OperandsInArithmeticExponentiationRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Pow;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Pow as AssignOpPow;
8+
use PhpParser\Node\Expr\BinaryOp\Pow as BinaryOpPow;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -16,33 +17,46 @@ class OperandsInArithmeticExponentiationRule implements Rule
1617
/** @var OperatorRuleHelper */
1718
private $helper;
1819

19-
public function __construct(OperatorRuleHelper $helper)
20+
/** @var bool */
21+
private $bleedingEdge;
22+
23+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2024
{
2125
$this->helper = $helper;
26+
$this->bleedingEdge = $bleedingEdge;
2227
}
2328

2429
public function getNodeType(): string
2530
{
26-
return Pow::class;
31+
return Expr::class;
2732
}
2833

2934
/**
30-
* @param BooleanAnd $node
3135
* @return string[] errors
3236
*/
3337
public function processNode(Node $node, Scope $scope): array
3438
{
39+
if ($node instanceof BinaryOpPow) {
40+
$left = $node->left;
41+
$right = $node->right;
42+
} elseif ($node instanceof AssignOpPow && $this->bleedingEdge) {
43+
$left = $node->var;
44+
$right = $node->expr;
45+
} else {
46+
return [];
47+
}
48+
3549
$messages = [];
36-
$leftType = $scope->getType($node->left);
37-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
50+
$leftType = $scope->getType($left);
51+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
3852
$messages[] = sprintf(
3953
'Only numeric types are allowed in **, %s given on the left side.',
4054
$leftType->describe(VerbosityLevel::typeOnly())
4155
);
4256
}
4357

44-
$rightType = $scope->getType($node->right);
45-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
58+
$rightType = $scope->getType($right);
59+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
4660
$messages[] = sprintf(
4761
'Only numeric types are allowed in **, %s given on the right side.',
4862
$rightType->describe(VerbosityLevel::typeOnly())

‎src/Rules/Operators/OperandsInArithmeticModuloRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Mod;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Mod as AssignOpMod;
8+
use PhpParser\Node\Expr\BinaryOp\Mod as BinaryOpMod;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -16,33 +17,46 @@ class OperandsInArithmeticModuloRule implements Rule
1617
/** @var OperatorRuleHelper */
1718
private $helper;
1819

19-
public function __construct(OperatorRuleHelper $helper)
20+
/** @var bool */
21+
private $bleedingEdge;
22+
23+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2024
{
2125
$this->helper = $helper;
26+
$this->bleedingEdge = $bleedingEdge;
2227
}
2328

2429
public function getNodeType(): string
2530
{
26-
return Mod::class;
31+
return Expr::class;
2732
}
2833

2934
/**
30-
* @param BooleanAnd $node
3135
* @return string[] errors
3236
*/
3337
public function processNode(Node $node, Scope $scope): array
3438
{
39+
if ($node instanceof BinaryOpMod) {
40+
$left = $node->left;
41+
$right = $node->right;
42+
} elseif ($node instanceof AssignOpMod && $this->bleedingEdge) {
43+
$left = $node->var;
44+
$right = $node->expr;
45+
} else {
46+
return [];
47+
}
48+
3549
$messages = [];
36-
$leftType = $scope->getType($node->left);
37-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
50+
$leftType = $scope->getType($left);
51+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
3852
$messages[] = sprintf(
3953
'Only numeric types are allowed in %%, %s given on the left side.',
4054
$leftType->describe(VerbosityLevel::typeOnly())
4155
);
4256
}
4357

44-
$rightType = $scope->getType($node->right);
45-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
58+
$rightType = $scope->getType($right);
59+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
4660
$messages[] = sprintf(
4761
'Only numeric types are allowed in %%, %s given on the right side.',
4862
$rightType->describe(VerbosityLevel::typeOnly())

‎src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Mul;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Mul as AssignOpMul;
8+
use PhpParser\Node\Expr\BinaryOp\Mul as BinaryOpMul;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -16,33 +17,46 @@ class OperandsInArithmeticMultiplicationRule implements Rule
1617
/** @var OperatorRuleHelper */
1718
private $helper;
1819

19-
public function __construct(OperatorRuleHelper $helper)
20+
/** @var bool */
21+
private $bleedingEdge;
22+
23+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2024
{
2125
$this->helper = $helper;
26+
$this->bleedingEdge = $bleedingEdge;
2227
}
2328

2429
public function getNodeType(): string
2530
{
26-
return Mul::class;
31+
return Expr::class;
2732
}
2833

2934
/**
30-
* @param BooleanAnd $node
3135
* @return string[] errors
3236
*/
3337
public function processNode(Node $node, Scope $scope): array
3438
{
39+
if ($node instanceof BinaryOpMul) {
40+
$left = $node->left;
41+
$right = $node->right;
42+
} elseif ($node instanceof AssignOpMul && $this->bleedingEdge) {
43+
$left = $node->var;
44+
$right = $node->expr;
45+
} else {
46+
return [];
47+
}
48+
3549
$messages = [];
36-
$leftType = $scope->getType($node->left);
37-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
50+
$leftType = $scope->getType($left);
51+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
3852
$messages[] = sprintf(
3953
'Only numeric types are allowed in *, %s given on the left side.',
4054
$leftType->describe(VerbosityLevel::typeOnly())
4155
);
4256
}
4357

44-
$rightType = $scope->getType($node->right);
45-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
58+
$rightType = $scope->getType($right);
59+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
4660
$messages[] = sprintf(
4761
'Only numeric types are allowed in *, %s given on the right side.',
4862
$rightType->describe(VerbosityLevel::typeOnly())

‎src/Rules/Operators/OperandsInArithmeticSubtractionRule.php‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace PHPStan\Rules\Operators;
44

55
use PhpParser\Node;
6-
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
7-
use PhpParser\Node\Expr\BinaryOp\Minus;
6+
use PhpParser\Node\Expr;
7+
use PhpParser\Node\Expr\AssignOp\Minus as AssignOpMinus;
8+
use PhpParser\Node\Expr\BinaryOp\Minus as BinaryOpMinus;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Rules\Rule;
1011
use PHPStan\Type\VerbosityLevel;
@@ -16,33 +17,46 @@ class OperandsInArithmeticSubtractionRule implements Rule
1617
/** @var OperatorRuleHelper */
1718
private $helper;
1819

19-
public function __construct(OperatorRuleHelper $helper)
20+
/** @var bool */
21+
private $bleedingEdge;
22+
23+
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
2024
{
2125
$this->helper = $helper;
26+
$this->bleedingEdge = $bleedingEdge;
2227
}
2328

2429
public function getNodeType(): string
2530
{
26-
return Minus::class;
31+
return Expr::class;
2732
}
2833

2934
/**
30-
* @param BooleanAnd $node
3135
* @return string[] errors
3236
*/
3337
public function processNode(Node $node, Scope $scope): array
3438
{
39+
if ($node instanceof BinaryOpMinus) {
40+
$left = $node->left;
41+
$right = $node->right;
42+
} elseif ($node instanceof AssignOpMinus && $this->bleedingEdge) {
43+
$left = $node->var;
44+
$right = $node->expr;
45+
} else {
46+
return [];
47+
}
48+
3549
$messages = [];
36-
$leftType = $scope->getType($node->left);
37-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->left)) {
50+
$leftType = $scope->getType($left);
51+
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
3852
$messages[] = sprintf(
3953
'Only numeric types are allowed in -, %s given on the left side.',
4054
$leftType->describe(VerbosityLevel::typeOnly())
4155
);
4256
}
4357

44-
$rightType = $scope->getType($node->right);
45-
if (!$this->helper->isValidForArithmeticOperation($scope, $node->right)) {
58+
$rightType = $scope->getType($right);
59+
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
4660
$messages[] = sprintf(
4761
'Only numeric types are allowed in -, %s given on the right side.',
4862
$rightType->describe(VerbosityLevel::typeOnly())

‎tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPStan\Rules\Rule;
66
use PHPStan\Rules\RuleLevelHelper;
77
use PHPStan\Testing\RuleTestCase;
8+
use function array_merge;
89
use const PHP_VERSION_ID;
910

1011
class OperandsInArithmeticAdditionRuleTest extends RuleTestCase
@@ -15,7 +16,8 @@ protected function getRule(): Rule
1516
return new OperandsInArithmeticAdditionRule(
1617
new OperatorRuleHelper(
1718
self::getContainer()->getByType(RuleLevelHelper::class)
18-
)
19+
),
20+
true
1921
);
2022
}
2123

@@ -31,12 +33,28 @@ public function testRule(): void
3133
29,
3234
],
3335
];
36+
3437
if (PHP_VERSION_ID < 80000) {
3538
$messages[] = [
3639
'Only numeric types are allowed in +, (array<int, string>|false) given on the left side.',
3740
110,
3841
];
3942
}
43+
44+
$messages = array_merge(
45+
$messages,
46+
[
47+
[
48+
'Only numeric types are allowed in +, null given on the right side.',
49+
132,
50+
],
51+
[
52+
'Only numeric types are allowed in +, null given on the right side.',
53+
133,
54+
],
55+
]
56+
);
57+
4058
$this->analyse([__DIR__ . '/data/operators.php'], $messages);
4159
}
4260

‎tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ protected function getRule(): Rule
1414
return new OperandsInArithmeticDivisionRule(
1515
new OperatorRuleHelper(
1616
self::getContainer()->getByType(RuleLevelHelper::class)
17-
)
17+
),
18+
true
1819
);
1920
}
2021

@@ -29,6 +30,14 @@ public function testRule(): void
2930
'Only numeric types are allowed in /, null given on the right side.',
3031
68,
3132
],
33+
[
34+
'Only numeric types are allowed in /, null given on the right side.',
35+
171,
36+
],
37+
[
38+
'Only numeric types are allowed in /, null given on the right side.',
39+
172,
40+
],
3241
]);
3342
}
3443

‎tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ protected function getRule(): Rule
1414
return new OperandsInArithmeticExponentiationRule(
1515
new OperatorRuleHelper(
1616
self::getContainer()->getByType(RuleLevelHelper::class)
17-
)
17+
),
18+
true
1819
);
1920
}
2021

@@ -29,6 +30,14 @@ public function testRule(): void
2930
'Only numeric types are allowed in **, null given on the right side.',
3031
81,
3132
],
33+
[
34+
'Only numeric types are allowed in **, null given on the right side.',
35+
184,
36+
],
37+
[
38+
'Only numeric types are allowed in **, null given on the right side.',
39+
185,
40+
],
3241
]);
3342
}
3443

‎tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ protected function getRule(): Rule
1414
return new OperandsInArithmeticModuloRule(
1515
new OperatorRuleHelper(
1616
self::getContainer()->getByType(RuleLevelHelper::class)
17-
)
17+
),
18+
true
1819
);
1920
}
2021

@@ -29,6 +30,14 @@ public function testRule(): void
2930
'Only numeric types are allowed in %, null given on the right side.',
3031
94,
3132
],
33+
[
34+
'Only numeric types are allowed in %, null given on the right side.',
35+
197,
36+
],
37+
[
38+
'Only numeric types are allowed in %, null given on the right side.',
39+
198,
40+
],
3241
]);
3342
}
3443

‎tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ protected function getRule(): Rule
1414
return new OperandsInArithmeticMultiplicationRule(
1515
new OperatorRuleHelper(
1616
self::getContainer()->getByType(RuleLevelHelper::class)
17-
)
17+
),
18+
true
1819
);
1920
}
2021

@@ -29,6 +30,14 @@ public function testRule(): void
2930
'Only numeric types are allowed in *, null given on the right side.',
3031
55,
3132
],
33+
[
34+
'Only numeric types are allowed in *, null given on the right side.',
35+
158,
36+
],
37+
[
38+
'Only numeric types are allowed in *, null given on the right side.',
39+
159,
40+
],
3241
]);
3342
}
3443

‎tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ protected function getRule(): Rule
1414
return new OperandsInArithmeticSubtractionRule(
1515
new OperatorRuleHelper(
1616
self::getContainer()->getByType(RuleLevelHelper::class)
17-
)
17+
),
18+
true
1819
);
1920
}
2021

@@ -29,6 +30,14 @@ public function testRule(): void
2930
'Only numeric types are allowed in -, null given on the right side.',
3031
42,
3132
],
33+
[
34+
'Only numeric types are allowed in -, null given on the right side.',
35+
145,
36+
],
37+
[
38+
'Only numeric types are allowed in -, null given on the right side.',
39+
146,
40+
],
3241
]);
3342
}
3443

‎tests/Rules/Operators/data/operators.php‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,101 @@ function (array $array, int $int, $mixed) {
117117
function (\ReflectionClass $ref): void {
118118
print_r(class_parents($ref->getName()) + class_implements($ref->getName()));
119119
};
120+
121+
$int += $int;
122+
$int += $float;
123+
$float += $int;
124+
$float += $float;
125+
$int += $float + $int;
126+
$intOrFloat += $int;
127+
$array += $array;
128+
$array += $array + $array;
129+
$int += $string;
130+
$int += $array;
131+
$int += $object;
132+
$int += $null;
133+
$int += $float + $string + $null;
134+
$array += $float + $array + $int;
135+
136+
$int -= $int;
137+
$int -= $float;
138+
$float -= $int;
139+
$float -= $float;
140+
$int -= $float - $int;
141+
$intOrFloat -= $int;
142+
$int -= $string;
143+
$int -= $array;
144+
$int -= $object;
145+
$int -= $null;
146+
$int -= $float - $string - $null;
147+
$array -= $float - $array - $int;
148+
149+
$int *= $int;
150+
$int *= $float;
151+
$float *= $int;
152+
$float *= $float;
153+
$int *= $float * $int;
154+
$intOrFloat *= $int;
155+
$int *= $string;
156+
$int *= $array;
157+
$int *= $object;
158+
$int *= $null;
159+
$int *= $float * $string * $null;
160+
$array *= $float * $array * $int;
161+
162+
$int /= $int;
163+
$int /= $float;
164+
$float /= $int;
165+
$float /= $float;
166+
$int /= $float /= $int;
167+
$intOrFloat /= $int;
168+
$int /= $string;
169+
$int /= $array;
170+
$int /= $object;
171+
$int /= $null;
172+
$int /= $float / $string / $null;
173+
$array /= $float / $array / $int;
174+
175+
$int **= $int;
176+
$int **= $float;
177+
$float **= $int;
178+
$float **= $float;
179+
$int **= $float **= $int;
180+
$intOrFloat **= $int;
181+
$int **= $string;
182+
$int **= $array;
183+
$int **= $object;
184+
$int **= $null;
185+
$int **= $float ** $string ** $null;
186+
$array **= $float ** $array ** $int;
187+
188+
$int %= $int;
189+
$int %= $float;
190+
$float %= $int;
191+
$float %= $float;
192+
$int %= $float %= $int;
193+
$intOrFloat %= $int;
194+
$int %= $string;
195+
$int %= $array;
196+
$int %= $object;
197+
$int %= $null;
198+
$int %= $float % $string % $null;
199+
$array %= $float % $array % $int;
200+
201+
function ($mixed, int $a, string $b) {
202+
$mixed += $mixed;
203+
$mixed += $a;
204+
$a += $mixed;
205+
$mixed += $b;
206+
$b += $mixed;
207+
};
208+
209+
function (array $array, int $int, $mixed) {
210+
foreach ($array as $i => $val) {
211+
$i += $int;
212+
}
213+
};
214+
215+
/** @var numeric-string $numericString */
216+
$numericString = doFoo();
217+
$numericString += 1;

0 commit comments

Comments
 (0)
Please sign in to comment.