Skip to content

Commit 9843dd8

Browse files
committed
Extract AllowedArrayKeysTypes::narrowOffsetKeyType() to ease re-use
1 parent 30e8e8b commit 9843dd8

File tree

2 files changed

+58
-41
lines changed

2 files changed

+58
-41
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
2929
use PHPStan\Reflection\ReflectionProvider;
3030
use PHPStan\Reflection\ResolvedFunctionVariant;
31+
use PHPStan\Rules\Arrays\AllowedArrayKeysTypes;
3132
use PHPStan\ShouldNotHappenException;
3233
use PHPStan\TrinaryLogic;
3334
use PHPStan\Type\Accessory\AccessoryArrayListType;
@@ -820,47 +821,8 @@ public function specifyTypesInCondition(
820821
);
821822
} else {
822823
$varType = $scope->getType($var->var);
823-
if ($varType->isArray()->yes() && !$varType->isIterableAtLeastOnce()->no()) {
824-
$varIterableKeyType = $varType->getIterableKeyType();
825-
826-
if ($varIterableKeyType->isConstantScalarValue()->yes()) {
827-
$narrowedKey = TypeCombinator::union(
828-
$varIterableKeyType,
829-
TypeCombinator::remove($varIterableKeyType->toString(), new ConstantStringType('')),
830-
);
831-
832-
if (!$varType->hasOffsetValueType(new ConstantIntegerType(0))->no()) {
833-
$narrowedKey = TypeCombinator::union(
834-
$narrowedKey,
835-
new ConstantBooleanType(false),
836-
);
837-
}
838-
839-
if (!$varType->hasOffsetValueType(new ConstantIntegerType(1))->no()) {
840-
$narrowedKey = TypeCombinator::union(
841-
$narrowedKey,
842-
new ConstantBooleanType(true),
843-
);
844-
}
845-
846-
if (!$varType->hasOffsetValueType(new ConstantStringType(''))->no()) {
847-
$narrowedKey = TypeCombinator::addNull($narrowedKey);
848-
}
849-
850-
if (!$varIterableKeyType->isNumericString()->no() || !$varIterableKeyType->isInteger()->no()) {
851-
$narrowedKey = TypeCombinator::union($narrowedKey, new FloatType());
852-
}
853-
} else {
854-
$narrowedKey = new MixedType(
855-
false,
856-
new UnionType([
857-
new ArrayType(new MixedType(), new MixedType()),
858-
new ObjectWithoutClassType(),
859-
new ResourceType(),
860-
]),
861-
);
862-
}
863-
824+
$narrowedKey = AllowedArrayKeysTypes::narrowOffsetKeyType($varType);
825+
if ($narrowedKey !== null) {
864826
$types = $types->unionWith(
865827
$this->create(
866828
$var->dim,

src/Rules/Arrays/AllowedArrayKeysTypes.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@
22

33
namespace PHPStan\Rules\Arrays;
44

5+
use PHPStan\Type\ArrayType;
56
use PHPStan\Type\BooleanType;
7+
use PHPStan\Type\Constant\ConstantBooleanType;
8+
use PHPStan\Type\Constant\ConstantIntegerType;
9+
use PHPStan\Type\Constant\ConstantStringType;
610
use PHPStan\Type\FloatType;
711
use PHPStan\Type\IntegerType;
12+
use PHPStan\Type\MixedType;
813
use PHPStan\Type\NullType;
14+
use PHPStan\Type\ObjectWithoutClassType;
15+
use PHPStan\Type\ResourceType;
916
use PHPStan\Type\StringType;
1017
use PHPStan\Type\Type;
18+
use PHPStan\Type\TypeCombinator;
1119
use PHPStan\Type\UnionType;
1220

1321
final class AllowedArrayKeysTypes
@@ -24,4 +32,51 @@ public static function getType(): Type
2432
]);
2533
}
2634

35+
public static function narrowOffsetKeyType(Type $varType): ?Type {
36+
if (!$varType->isArray()->yes() || $varType->isIterableAtLeastOnce()->no()) {
37+
return null;
38+
}
39+
40+
$varIterableKeyType = $varType->getIterableKeyType();
41+
42+
if ($varIterableKeyType->isConstantScalarValue()->yes()) {
43+
$narrowedKey = TypeCombinator::union(
44+
$varIterableKeyType,
45+
TypeCombinator::remove($varIterableKeyType->toString(), new ConstantStringType('')),
46+
);
47+
48+
if (!$varType->hasOffsetValueType(new ConstantIntegerType(0))->no()) {
49+
$narrowedKey = TypeCombinator::union(
50+
$narrowedKey,
51+
new ConstantBooleanType(false),
52+
);
53+
}
54+
55+
if (!$varType->hasOffsetValueType(new ConstantIntegerType(1))->no()) {
56+
$narrowedKey = TypeCombinator::union(
57+
$narrowedKey,
58+
new ConstantBooleanType(true),
59+
);
60+
}
61+
62+
if (!$varType->hasOffsetValueType(new ConstantStringType(''))->no()) {
63+
$narrowedKey = TypeCombinator::addNull($narrowedKey);
64+
}
65+
66+
if (!$varIterableKeyType->isNumericString()->no() || !$varIterableKeyType->isInteger()->no()) {
67+
$narrowedKey = TypeCombinator::union($narrowedKey, new FloatType());
68+
}
69+
} else {
70+
$narrowedKey = new MixedType(
71+
false,
72+
new UnionType([
73+
new ArrayType(new MixedType(), new MixedType()),
74+
new ObjectWithoutClassType(),
75+
new ResourceType(),
76+
]),
77+
);
78+
}
79+
80+
return $narrowedKey;
81+
}
2782
}

0 commit comments

Comments
 (0)