22
33namespace PHPStan \Rules \Arrays ;
44
5+ use PHPStan \Type \ArrayType ;
56use PHPStan \Type \BooleanType ;
7+ use PHPStan \Type \Constant \ConstantBooleanType ;
8+ use PHPStan \Type \Constant \ConstantIntegerType ;
9+ use PHPStan \Type \Constant \ConstantStringType ;
610use PHPStan \Type \FloatType ;
711use PHPStan \Type \IntegerType ;
12+ use PHPStan \Type \MixedType ;
813use PHPStan \Type \NullType ;
14+ use PHPStan \Type \ObjectWithoutClassType ;
15+ use PHPStan \Type \ResourceType ;
916use PHPStan \Type \StringType ;
1017use PHPStan \Type \Type ;
18+ use PHPStan \Type \TypeCombinator ;
1119use PHPStan \Type \UnionType ;
1220
1321final 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