|
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