Skip to content

Commit ba3f7ed

Browse files
authored
RuleLevelHelper::findTypeToCheck - make null-safe shortcircuiting optional
1 parent 5670cf2 commit ba3f7ed

File tree

48 files changed

+559
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+559
-21
lines changed

src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Rules\Arrays;
44

55
use PhpParser\Node\Expr;
6+
use PHPStan\Analyser\NullsafeOperatorHelper;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Rules\RuleError;
89
use PHPStan\Rules\RuleErrorBuilder;
@@ -43,7 +44,7 @@ public function check(
4344
{
4445
$typeResult = $this->ruleLevelHelper->findTypeToCheck(
4546
$scope,
46-
$var,
47+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($var),
4748
$unknownClassPattern,
4849
static function (Type $type) use ($dimType): bool {
4950
return $type->hasOffsetValueType($dimType)->yes();

src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php

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

33
namespace PHPStan\Rules\Arrays;
44

5+
use PHPStan\Analyser\NullsafeOperatorHelper;
56
use PHPStan\Analyser\Scope;
67
use PHPStan\Internal\SprintfHelper;
78
use PHPStan\Rules\RuleErrorBuilder;
@@ -50,7 +51,7 @@ public function processNode(\PhpParser\Node $node, Scope $scope): array
5051

5152
$isOffsetAccessibleTypeResult = $this->ruleLevelHelper->findTypeToCheck(
5253
$scope,
53-
$node->var,
54+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($node->var),
5455
$unknownClassPattern,
5556
static function (Type $type): bool {
5657
return $type->isOffsetAccessible()->yes();

src/Rules/Arrays/OffsetAccessAssignmentRule.php

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

33
namespace PHPStan\Rules\Arrays;
44

5+
use PHPStan\Analyser\NullsafeOperatorHelper;
56
use PHPStan\Analyser\Scope;
67
use PHPStan\Rules\RuleErrorBuilder;
78
use PHPStan\Rules\RuleLevelHelper;
@@ -41,7 +42,7 @@ public function processNode(\PhpParser\Node $node, Scope $scope): array
4142

4243
$varTypeResult = $this->ruleLevelHelper->findTypeToCheck(
4344
$scope,
44-
$node->var,
45+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($node->var),
4546
'',
4647
static function (Type $varType) use ($potentialDimType): bool {
4748
$arrayDimType = $varType->setOffsetValueType($potentialDimType, new MixedType());

src/Rules/Classes/ClassConstantRule.php

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

55
use PhpParser\Node;
66
use PhpParser\Node\Expr\ClassConstFetch;
7+
use PHPStan\Analyser\NullsafeOperatorHelper;
78
use PHPStan\Analyser\Scope;
89
use PHPStan\Internal\SprintfHelper;
910
use PHPStan\Php\PhpVersion;
@@ -118,7 +119,7 @@ public function processNode(Node $node, Scope $scope): array
118119
} else {
119120
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
120121
$scope,
121-
$class,
122+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($class),
122123
sprintf('Access to constant %s on an unknown class %%s.', SprintfHelper::escapeFormatString($constantName)),
123124
static function (Type $type) use ($constantName): bool {
124125
return $type->canAccessConstants()->yes() && $type->hasConstant($constantName)->yes();

src/Rules/Functions/CallCallablesRule.php

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

33
namespace PHPStan\Rules\Functions;
44

5+
use PHPStan\Analyser\NullsafeOperatorHelper;
56
use PHPStan\Analyser\Scope;
67
use PHPStan\Internal\SprintfHelper;
78
use PHPStan\Reflection\InaccessibleMethod;
@@ -53,7 +54,7 @@ public function processNode(
5354

5455
$typeResult = $this->ruleLevelHelper->findTypeToCheck(
5556
$scope,
56-
$node->name,
57+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($node->name),
5758
'Invoking callable on an unknown class %s.',
5859
static function (Type $type): bool {
5960
return $type->isCallable()->yes();

src/Rules/Methods/CallMethodsRule.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpParser\Node;
66
use PhpParser\Node\Expr\MethodCall;
7+
use PHPStan\Analyser\NullsafeOperatorHelper;
78
use PHPStan\Analyser\Scope;
89
use PHPStan\Internal\SprintfHelper;
910
use PHPStan\Reflection\ParametersAcceptorSelector;
@@ -58,9 +59,10 @@ public function processNode(Node $node, Scope $scope): array
5859
}
5960

6061
$name = $node->name->name;
62+
6163
$typeResult = $this->ruleLevelHelper->findTypeToCheck(
6264
$scope,
63-
$node->var,
65+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($node->var),
6466
sprintf('Call to method %s() on an unknown class %%s.', SprintfHelper::escapeFormatString($name)),
6567
static function (Type $type) use ($name): bool {
6668
return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes();

src/Rules/Methods/CallStaticMethodsRule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PhpParser\Node;
66
use PhpParser\Node\Expr\StaticCall;
77
use PhpParser\Node\Name;
8+
use PHPStan\Analyser\NullsafeOperatorHelper;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Internal\SprintfHelper;
1011
use PHPStan\Reflection\MethodReflection;
@@ -150,7 +151,7 @@ public function processNode(Node $node, Scope $scope): array
150151
} else {
151152
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
152153
$scope,
153-
$class,
154+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($class),
154155
sprintf('Call to static method %s() on an unknown class %%s.', SprintfHelper::escapeFormatString($methodName)),
155156
static function (Type $type) use ($methodName): bool {
156157
return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes();

src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Rules\Methods;
44

55
use PhpParser\Node;
6+
use PHPStan\Analyser\NullsafeOperatorHelper;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Rules\Rule;
89
use PHPStan\Rules\RuleErrorBuilder;
@@ -46,7 +47,7 @@ public function processNode(Node $node, Scope $scope): array
4647

4748
$typeResult = $this->ruleLevelHelper->findTypeToCheck(
4849
$scope,
49-
$methodCall->var,
50+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($methodCall->var),
5051
'',
5152
static function (Type $type) use ($methodName): bool {
5253
return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes();

src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Rules\Methods;
44

55
use PhpParser\Node;
6+
use PHPStan\Analyser\NullsafeOperatorHelper;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Reflection\ReflectionProvider;
89
use PHPStan\Rules\Rule;
@@ -60,7 +61,7 @@ public function processNode(Node $node, Scope $scope): array
6061
} else {
6162
$typeResult = $this->ruleLevelHelper->findTypeToCheck(
6263
$scope,
63-
$staticCall->class,
64+
NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($staticCall->class),
6465
'',
6566
static function (Type $type) use ($methodName): bool {
6667
return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes();

src/Rules/Operators/InvalidComparisonOperationRule.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
use PHPStan\Type\ErrorType;
1010
use PHPStan\Type\FloatType;
1111
use PHPStan\Type\IntegerType;
12+
use PHPStan\Type\NullType;
1213
use PHPStan\Type\ObjectWithoutClassType;
1314
use PHPStan\Type\Type;
15+
use PHPStan\Type\TypeCombinator;
1416
use PHPStan\Type\UnionType;
1517
use PHPStan\Type\VerbosityLevel;
1618

@@ -48,10 +50,10 @@ public function processNode(Node $node, Scope $scope): array
4850

4951
if (
5052
($this->isNumberType($scope, $node->left) && (
51-
$this->isObjectType($scope, $node->right) || $this->isArrayType($scope, $node->right)
53+
$this->isPossiblyNullableObjectType($scope, $node->right) || $this->isPossiblyNullableArrayType($scope, $node->right)
5254
))
5355
|| ($this->isNumberType($scope, $node->right) && (
54-
$this->isObjectType($scope, $node->left) || $this->isArrayType($scope, $node->left)
56+
$this->isPossiblyNullableObjectType($scope, $node->left) || $this->isPossiblyNullableArrayType($scope, $node->left)
5557
))
5658
) {
5759
return [
@@ -86,7 +88,7 @@ private function isNumberType(Scope $scope, Node\Expr $expr): bool
8688
return !$acceptedType->isSuperTypeOf($type)->no();
8789
}
8890

89-
private function isObjectType(Scope $scope, Node\Expr $expr): bool
91+
private function isPossiblyNullableObjectType(Scope $scope, Node\Expr $expr): bool
9092
{
9193
$acceptedType = new ObjectWithoutClassType();
9294

@@ -103,6 +105,10 @@ static function (Type $type) use ($acceptedType): bool {
103105
return false;
104106
}
105107

108+
if (TypeCombinator::containsNull($type) && !$type instanceof NullType) {
109+
$type = TypeCombinator::removeNull($type);
110+
}
111+
106112
$isSuperType = $acceptedType->isSuperTypeOf($type);
107113
if ($type instanceof \PHPStan\Type\BenevolentUnionType) {
108114
return !$isSuperType->no();
@@ -111,7 +117,7 @@ static function (Type $type) use ($acceptedType): bool {
111117
return $isSuperType->yes();
112118
}
113119

114-
private function isArrayType(Scope $scope, Node\Expr $expr): bool
120+
private function isPossiblyNullableArrayType(Scope $scope, Node\Expr $expr): bool
115121
{
116122
$type = $this->ruleLevelHelper->findTypeToCheck(
117123
$scope,
@@ -122,6 +128,10 @@ static function (Type $type): bool {
122128
}
123129
)->getType();
124130

131+
if (TypeCombinator::containsNull($type) && !$type instanceof NullType) {
132+
$type = TypeCombinator::removeNull($type);
133+
}
134+
125135
return !($type instanceof ErrorType) && $type->isArray()->yes();
126136
}
127137

0 commit comments

Comments
 (0)