Skip to content

Commit f820776

Browse files
committed
Fix wrong scope in BooleanInBooleanAndRule and BooleanInBooleanOrRule
1 parent fb24448 commit f820776

File tree

7 files changed

+74
-65
lines changed

7 files changed

+74
-65
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
],
88
"require": {
99
"php": "^7.1 || ^8.0",
10-
"phpstan/phpstan": "^0.12.60"
10+
"phpstan/phpstan": "^0.12.66"
1111
},
1212
"require-dev": {
1313
"phing/phing": "^2.16.3",

phpstan-baseline.neon

-40
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,6 @@
22

33
parameters:
44
ignoreErrors:
5-
-
6-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanAndRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
7-
count: 1
8-
path: src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php
9-
10-
-
11-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanAnd\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanAndRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
12-
count: 1
13-
path: src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php
14-
155
-
166
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
177
count: 1
@@ -22,16 +12,6 @@ parameters:
2212
count: 1
2313
path: src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php
2414

25-
-
26-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanOrRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
27-
count: 1
28-
path: src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php
29-
30-
-
31-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BinaryOp\\\\BooleanOr\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanOrRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
32-
count: 1
33-
path: src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php
34-
3515
-
3616
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
3717
count: 1
@@ -282,16 +262,6 @@ parameters:
282262
count: 1
283263
path: src/Rules/VariableVariables/VariableVariablesRule.php
284264

285-
-
286-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanAndRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
287-
count: 1
288-
path: tests/Rules/BooleansInConditions/BooleanInBooleanAndRuleTest.php
289-
290-
-
291-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanAndRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
292-
count: 1
293-
path: tests/Rules/BooleansInConditions/BooleanInBooleanAndRuleTest.php
294-
295265
-
296266
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
297267
count: 1
@@ -302,16 +272,6 @@ parameters:
302272
count: 1
303273
path: tests/Rules/BooleansInConditions/BooleanInBooleanNotRuleTest.php
304274

305-
-
306-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanOrRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
307-
count: 1
308-
path: tests/Rules/BooleansInConditions/BooleanInBooleanOrRuleTest.php
309-
310-
-
311-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanOrRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
312-
count: 1
313-
path: tests/Rules/BooleansInConditions/BooleanInBooleanOrRuleTest.php
314-
315275
-
316276
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
317277
count: 1

src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php

+16-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
namespace PHPStan\Rules\BooleansInConditions;
44

5+
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
6+
use PHPStan\Node\BooleanAndNode;
57
use PHPStan\Type\VerbosityLevel;
68

9+
/**
10+
* @implements \PHPStan\Rules\Rule<BooleanAndNode>
11+
*/
712
class BooleanInBooleanAndRule implements \PHPStan\Rules\Rule
813
{
914

@@ -17,27 +22,28 @@ public function __construct(BooleanRuleHelper $helper)
1722

1823
public function getNodeType(): string
1924
{
20-
return \PhpParser\Node\Expr\BinaryOp\BooleanAnd::class;
25+
return BooleanAndNode::class;
2126
}
2227

23-
/**
24-
* @param \PhpParser\Node\Expr\BinaryOp\BooleanAnd $node
25-
* @param \PHPStan\Analyser\Scope $scope
26-
* @return string[] errors
27-
*/
2828
public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
2929
{
30+
$originalNode = $node->getOriginalNode();
31+
if (!$originalNode instanceof BooleanAnd) {
32+
return [];
33+
}
34+
3035
$messages = [];
31-
if (!$this->helper->passesAsBoolean($scope, $node->left)) {
32-
$leftType = $scope->getType($node->left);
36+
if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) {
37+
$leftType = $scope->getType($originalNode->left);
3338
$messages[] = sprintf(
3439
'Only booleans are allowed in &&, %s given on the left side.',
3540
$leftType->describe(VerbosityLevel::typeOnly())
3641
);
3742
}
3843

39-
$rightType = $scope->getType($node->right);
40-
if (!$this->helper->passesAsBoolean($scope, $node->right)) {
44+
$rightScope = $node->getRightScope();
45+
if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) {
46+
$rightType = $rightScope->getType($originalNode->right);
4147
$messages[] = sprintf(
4248
'Only booleans are allowed in &&, %s given on the right side.',
4349
$rightType->describe(VerbosityLevel::typeOnly())

src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php

+16-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
namespace PHPStan\Rules\BooleansInConditions;
44

5+
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
6+
use PHPStan\Node\BooleanOrNode;
57
use PHPStan\Type\VerbosityLevel;
68

9+
/**
10+
* @implements \PHPStan\Rules\Rule<BooleanOrNode>
11+
*/
712
class BooleanInBooleanOrRule implements \PHPStan\Rules\Rule
813
{
914

@@ -17,27 +22,28 @@ public function __construct(BooleanRuleHelper $helper)
1722

1823
public function getNodeType(): string
1924
{
20-
return \PhpParser\Node\Expr\BinaryOp\BooleanOr::class;
25+
return BooleanOrNode::class;
2126
}
2227

23-
/**
24-
* @param \PhpParser\Node\Expr\BinaryOp\BooleanOr $node
25-
* @param \PHPStan\Analyser\Scope $scope
26-
* @return string[] errors
27-
*/
2828
public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
2929
{
30+
$originalNode = $node->getOriginalNode();
31+
if (!$originalNode instanceof BooleanOr) {
32+
return [];
33+
}
34+
3035
$messages = [];
31-
if (!$this->helper->passesAsBoolean($scope, $node->left)) {
32-
$leftType = $scope->getType($node->left);
36+
if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) {
37+
$leftType = $scope->getType($originalNode->left);
3338
$messages[] = sprintf(
3439
'Only booleans are allowed in ||, %s given on the left side.',
3540
$leftType->describe(VerbosityLevel::typeOnly())
3641
);
3742
}
3843

39-
if (!$this->helper->passesAsBoolean($scope, $node->right)) {
40-
$rightType = $scope->getType($node->right);
44+
$rightScope = $node->getRightScope();
45+
if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) {
46+
$rightType = $rightScope->getType($originalNode->right);
4147
$messages[] = sprintf(
4248
'Only booleans are allowed in ||, %s given on the right side.',
4349
$rightType->describe(VerbosityLevel::typeOnly())

tests/Rules/BooleansInConditions/BooleanInBooleanAndRuleTest.php

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use PHPStan\Rules\Rule;
66
use PHPStan\Rules\RuleLevelHelper;
77

8+
/**
9+
* @extends \PHPStan\Testing\RuleTestCase<BooleanInBooleanAndRule>
10+
*/
811
class BooleanInBooleanAndRuleTest extends \PHPStan\Testing\RuleTestCase
912
{
1013

@@ -48,4 +51,14 @@ public function testRule(): void
4851
]);
4952
}
5053

54+
public function testBug104(): void
55+
{
56+
$this->analyse([__DIR__ . '/data/bug-104.php'], [
57+
[
58+
'Only booleans are allowed in &&, string given on the right side.',
59+
13,
60+
],
61+
]);
62+
}
63+
5164
}

tests/Rules/BooleansInConditions/BooleanInBooleanOrRuleTest.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use PHPStan\Rules\Rule;
66
use PHPStan\Rules\RuleLevelHelper;
77

8+
/**
9+
* @extends \PHPStan\Testing\RuleTestCase<BooleanInBooleanOrRule>
10+
*/
811
class BooleanInBooleanOrRuleTest extends \PHPStan\Testing\RuleTestCase
912
{
1013

@@ -37,10 +40,6 @@ public function testRule(): void
3740
'Only booleans are allowed in ||, string given on the left side.',
3841
27,
3942
],
40-
[
41-
'Only booleans are allowed in ||, string given on the right side.',
42-
27,
43-
],
4443
[
4544
'Only booleans are allowed in ||, mixed given on the right side.',
4645
29,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Bug104;
4+
5+
class Foo
6+
{
7+
8+
public function foo(?string $bar): void
9+
{
10+
if ($bar !== null && strpos($bar, 'bar') === 0) {
11+
echo 'strpos works';
12+
}
13+
if ($bar !== null && $bar) {
14+
echo 'string as boolean does not';
15+
}
16+
}
17+
18+
public function bar(?bool $bar): void
19+
{
20+
if ($bar !== null && $bar) {
21+
echo 'foo';
22+
}
23+
}
24+
25+
}

0 commit comments

Comments
 (0)