|
9 | 9 | use PHPStan\Rules\RuleErrorBuilder;
|
10 | 10 | use PHPStan\Rules\RuleLevelHelper;
|
11 | 11 | use PHPStan\ShouldNotHappenException;
|
12 |
| -use PHPStan\Type\BenevolentUnionType; |
| 12 | +use PHPStan\Type\ArrayType; |
13 | 13 | use PHPStan\Type\ErrorType;
|
14 | 14 | use PHPStan\Type\FloatType;
|
15 | 15 | use PHPStan\Type\IntegerType;
|
| 16 | +use PHPStan\Type\MixedType; |
| 17 | +use PHPStan\Type\NullType; |
16 | 18 | use PHPStan\Type\ObjectWithoutClassType;
|
17 | 19 | use PHPStan\Type\Type;
|
18 |
| -use PHPStan\Type\TypeCombinator; |
19 | 20 | use PHPStan\Type\UnionType;
|
20 | 21 | use PHPStan\Type\VerbosityLevel;
|
21 | 22 | use function get_class;
|
@@ -51,15 +52,17 @@ public function processNode(Node $node, Scope $scope): array
|
51 | 52 | return [];
|
52 | 53 | }
|
53 | 54 |
|
54 |
| - if ($this->isNumberType($scope, $node->left) && $this->isNumberType($scope, $node->right)) { |
| 55 | + $isLeftNumberType = $this->isNumberType($scope, $node->left); |
| 56 | + $isRightNumberType = $this->isNumberType($scope, $node->right); |
| 57 | + if (($isLeftNumberType && $isRightNumberType) || (!$isLeftNumberType && !$isRightNumberType)) { |
55 | 58 | return [];
|
56 | 59 | }
|
57 | 60 |
|
58 | 61 | if (
|
59 |
| - ($this->isNumberType($scope, $node->left) && ( |
| 62 | + ($isLeftNumberType && ( |
60 | 63 | $this->isPossiblyNullableObjectType($scope, $node->right) || $this->isPossiblyNullableArrayType($scope, $node->right)
|
61 | 64 | ))
|
62 |
| - || ($this->isNumberType($scope, $node->right) && ( |
| 65 | + || ($isRightNumberType && ( |
63 | 66 | $this->isPossiblyNullableObjectType($scope, $node->left) || $this->isPossiblyNullableArrayType($scope, $node->left)
|
64 | 67 | ))
|
65 | 68 | ) {
|
@@ -125,45 +128,18 @@ private function isNumberType(Scope $scope, Node\Expr $expr): bool
|
125 | 128 |
|
126 | 129 | private function isPossiblyNullableObjectType(Scope $scope, Node\Expr $expr): bool
|
127 | 130 | {
|
128 |
| - $acceptedType = new ObjectWithoutClassType(); |
| 131 | + $type = $scope->getType($expr); |
| 132 | + $acceptedType = new UnionType([new ObjectWithoutClassType(), new NullType()]); |
129 | 133 |
|
130 |
| - $type = $this->ruleLevelHelper->findTypeToCheck( |
131 |
| - $scope, |
132 |
| - $expr, |
133 |
| - '', |
134 |
| - static fn (Type $type): bool => $acceptedType->isSuperTypeOf($type)->yes(), |
135 |
| - )->getType(); |
136 |
| - |
137 |
| - if ($type instanceof ErrorType) { |
138 |
| - return false; |
139 |
| - } |
140 |
| - |
141 |
| - if (TypeCombinator::containsNull($type) && !$type->isNull()->yes()) { |
142 |
| - $type = TypeCombinator::removeNull($type); |
143 |
| - } |
144 |
| - |
145 |
| - $isSuperType = $acceptedType->isSuperTypeOf($type); |
146 |
| - if ($type instanceof BenevolentUnionType) { |
147 |
| - return !$isSuperType->no(); |
148 |
| - } |
149 |
| - |
150 |
| - return $isSuperType->yes(); |
| 134 | + return !$type->isNull()->yes() && $acceptedType->isSuperTypeOf($type)->yes(); |
151 | 135 | }
|
152 | 136 |
|
153 | 137 | private function isPossiblyNullableArrayType(Scope $scope, Node\Expr $expr): bool
|
154 | 138 | {
|
155 |
| - $type = $this->ruleLevelHelper->findTypeToCheck( |
156 |
| - $scope, |
157 |
| - $expr, |
158 |
| - '', |
159 |
| - static fn (Type $type): bool => $type->isArray()->yes(), |
160 |
| - )->getType(); |
161 |
| - |
162 |
| - if (TypeCombinator::containsNull($type) && !$type->isNull()->yes()) { |
163 |
| - $type = TypeCombinator::removeNull($type); |
164 |
| - } |
| 139 | + $type = $scope->getType($expr); |
| 140 | + $acceptedType = new UnionType([new ArrayType(new MixedType(), new MixedType()), new NullType()]); |
165 | 141 |
|
166 |
| - return !($type instanceof ErrorType) && $type->isArray()->yes(); |
| 142 | + return !$type->isNull()->yes() && $acceptedType->isSuperTypeOf($type)->yes(); |
167 | 143 | }
|
168 | 144 |
|
169 | 145 | }
|
0 commit comments