2
2
3
3
namespace PHPStan \Rules \Arrays ;
4
4
5
+ use PHPStan \Type \ArrayType ;
5
6
use PHPStan \Type \BooleanType ;
7
+ use PHPStan \Type \Constant \ConstantBooleanType ;
8
+ use PHPStan \Type \Constant \ConstantIntegerType ;
9
+ use PHPStan \Type \Constant \ConstantStringType ;
6
10
use PHPStan \Type \FloatType ;
7
11
use PHPStan \Type \IntegerType ;
12
+ use PHPStan \Type \MixedType ;
8
13
use PHPStan \Type \NullType ;
14
+ use PHPStan \Type \ObjectWithoutClassType ;
15
+ use PHPStan \Type \ResourceType ;
9
16
use PHPStan \Type \StringType ;
10
17
use PHPStan \Type \Type ;
18
+ use PHPStan \Type \TypeCombinator ;
11
19
use PHPStan \Type \UnionType ;
12
20
13
21
final class AllowedArrayKeysTypes
@@ -24,4 +32,51 @@ public static function getType(): Type
24
32
]);
25
33
}
26
34
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
+ }
27
82
}
0 commit comments