Skip to content

Commit 23358d8

Browse files
committed
Refactoring - NullsafeCheck
1 parent cfc0fa7 commit 23358d8

4 files changed

Lines changed: 73 additions & 50 deletions

File tree

conf/config.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,9 @@ services:
691691
checkMissingIterableValueType: %checkMissingIterableValueType%
692692
checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType%
693693

694+
-
695+
class: PHPStan\Rules\NullsafeCheck
696+
694697
-
695698
class: PHPStan\Rules\Properties\LazyReadWritePropertiesExtensionProvider
696699

src/Rules/NullsafeCheck.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules;
4+
5+
use PhpParser\Node\Expr;
6+
7+
class NullsafeCheck
8+
{
9+
10+
public function containsNullSafe(Expr $expr): bool
11+
{
12+
if (
13+
$expr instanceof Expr\NullsafePropertyFetch
14+
|| $expr instanceof Expr\NullsafeMethodCall
15+
) {
16+
return true;
17+
}
18+
19+
if ($expr instanceof Expr\ArrayDimFetch) {
20+
return $this->containsNullSafe($expr->var);
21+
}
22+
23+
if ($expr instanceof Expr\PropertyFetch) {
24+
return $this->containsNullSafe($expr->var);
25+
}
26+
27+
if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) {
28+
return $this->containsNullSafe($expr->class);
29+
}
30+
31+
if ($expr instanceof Expr\MethodCall) {
32+
return $this->containsNullSafe($expr->var);
33+
}
34+
35+
if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) {
36+
return $this->containsNullSafe($expr->class);
37+
}
38+
39+
if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) {
40+
foreach ($expr->items as $item) {
41+
if ($item === null) {
42+
continue;
43+
}
44+
45+
if ($item->key !== null && $this->containsNullSafe($item->key)) {
46+
return true;
47+
}
48+
49+
if ($this->containsNullSafe($item->value)) {
50+
return true;
51+
}
52+
}
53+
}
54+
55+
return false;
56+
}
57+
58+
}

src/Rules/Operators/InvalidAssignVarRule.php

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpParser\Node\Expr\AssignOp;
99
use PhpParser\Node\Expr\AssignRef;
1010
use PHPStan\Analyser\Scope;
11+
use PHPStan\Rules\NullsafeCheck;
1112
use PHPStan\Rules\Rule;
1213
use PHPStan\Rules\RuleErrorBuilder;
1314

@@ -17,6 +18,13 @@
1718
class InvalidAssignVarRule implements Rule
1819
{
1920

21+
private NullsafeCheck $nullsafeCheck;
22+
23+
public function __construct(NullsafeCheck $nullsafeCheck)
24+
{
25+
$this->nullsafeCheck = $nullsafeCheck;
26+
}
27+
2028
public function getNodeType(): string
2129
{
2230
return Expr::class;
@@ -32,13 +40,13 @@ public function processNode(Node $node, Scope $scope): array
3240
return [];
3341
}
3442

35-
if ($this->containsNullSafe($node->var)) {
43+
if ($this->nullsafeCheck->containsNullSafe($node->var)) {
3644
return [
3745
RuleErrorBuilder::message('Nullsafe operator cannot be on left side of assignment.')->nonIgnorable()->build(),
3846
];
3947
}
4048

41-
if ($node instanceof AssignRef && $this->containsNullSafe($node->expr)) {
49+
if ($node instanceof AssignRef && $this->nullsafeCheck->containsNullSafe($node->expr)) {
4250
return [
4351
RuleErrorBuilder::message('Nullsafe operator cannot be on right side of assignment by reference.')->nonIgnorable()->build(),
4452
];
@@ -53,53 +61,6 @@ public function processNode(Node $node, Scope $scope): array
5361
return [];
5462
}
5563

56-
private function containsNullSafe(Expr $expr): bool
57-
{
58-
if (
59-
$expr instanceof Expr\NullsafePropertyFetch
60-
|| $expr instanceof Expr\NullsafeMethodCall
61-
) {
62-
return true;
63-
}
64-
65-
if ($expr instanceof Expr\ArrayDimFetch) {
66-
return $this->containsNullSafe($expr->var);
67-
}
68-
69-
if ($expr instanceof Expr\PropertyFetch) {
70-
return $this->containsNullSafe($expr->var);
71-
}
72-
73-
if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) {
74-
return $this->containsNullSafe($expr->class);
75-
}
76-
77-
if ($expr instanceof Expr\MethodCall) {
78-
return $this->containsNullSafe($expr->var);
79-
}
80-
81-
if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) {
82-
return $this->containsNullSafe($expr->class);
83-
}
84-
85-
if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) {
86-
foreach ($expr->items as $item) {
87-
if ($item === null) {
88-
continue;
89-
}
90-
91-
if ($item->key !== null && $this->containsNullSafe($item->key)) {
92-
return true;
93-
}
94-
95-
if ($this->containsNullSafe($item->value)) {
96-
return true;
97-
}
98-
}
99-
}
100-
101-
return false;
102-
}
10364

10465
private function containsNonAssignableExpression(Expr $expr): bool
10566
{

tests/PHPStan/Rules/Operators/InvalidAssignVarRuleTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Rules\Operators;
44

5+
use PHPStan\Rules\NullsafeCheck;
56
use PHPStan\Rules\Rule;
67
use PHPStan\Testing\RuleTestCase;
78

@@ -13,7 +14,7 @@ class InvalidAssignVarRuleTest extends RuleTestCase
1314

1415
protected function getRule(): Rule
1516
{
16-
return new InvalidAssignVarRule();
17+
return new InvalidAssignVarRule(new NullsafeCheck());
1718
}
1819

1920
public function testRule(): void

0 commit comments

Comments
 (0)