11
11
use PHPStan \Type \ArrayType ;
12
12
use PHPStan \Type \Constant \ConstantArrayTypeBuilder ;
13
13
use PHPStan \Type \Constant \ConstantIntegerType ;
14
+ use PHPStan \Type \Constant \ConstantStringType ;
14
15
use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
15
16
use PHPStan \Type \MixedType ;
16
17
use PHPStan \Type \NeverType ;
@@ -45,8 +46,6 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
45
46
46
47
$ functionName = strtolower ($ functionReflection ->getName ());
47
48
$ inputArgType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
48
-
49
- $ inputArrayType = $ inputArgType ->getArrays ()[0 ] ?? null ;
50
49
$ inputConstantArrayType = null ;
51
50
if ($ functionName === 'filter_var_array ' ) {
52
51
if ($ inputArgType ->isArray ()->no ()) {
@@ -69,14 +68,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
69
68
70
69
// Pragmatical solution since global expressions are not passed through the scope for performance reasons
71
70
// See https://github.com/phpstan/phpstan-src/pull/2012 for details
72
- $ inputArrayType = new ArrayType (new StringType (), new MixedType ());
73
- }
74
-
75
- if ($ inputArrayType === null ) {
76
- $ inputArrayType = new ArrayType (new MixedType (), new MixedType ());
77
- if ($ inputArgType ->isSuperTypeOf ($ inputArrayType )->no ()) {
78
- return null ;
79
- }
71
+ $ inputArgType = new ArrayType (new StringType (), new MixedType ());
80
72
}
81
73
82
74
$ filterArgType = $ scope ->getType ($ functionCall ->getArgs ()[1 ]->value );
@@ -90,11 +82,11 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
90
82
if ($ inputConstantArrayType === null ) {
91
83
$ isList = $ inputArgType ->isList ()->yes ();
92
84
$ valueType = $ this ->filterFunctionReturnTypeHelper ->getType (
93
- $ inputArrayType -> getItemType (),
85
+ $ inputArgType -> getIterableValueType (),
94
86
$ filterArgType ,
95
87
null ,
96
88
);
97
- $ arrayType = new ArrayType ($ inputArrayType -> getKeyType (), $ valueType );
89
+ $ arrayType = new ArrayType ($ inputArgType -> getIterableKeyType (), $ valueType );
98
90
99
91
return $ isList ? AccessoryArrayListType::intersectWith ($ arrayType ) : $ arrayType ;
100
92
}
@@ -116,11 +108,11 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
116
108
}
117
109
} elseif ($ filterConstantArrayType === null ) {
118
110
if ($ inputConstantArrayType === null ) {
119
- $ isList = $ inputArrayType ->isList ()->yes ();
120
- $ valueType = $ this ->filterFunctionReturnTypeHelper ->getType ($ inputArrayType , $ filterArgType , null );
111
+ $ isList = $ inputArgType ->isList ()->yes ();
112
+ $ valueType = $ this ->filterFunctionReturnTypeHelper ->getType ($ inputArgType , $ filterArgType , null );
121
113
122
114
$ arrayType = new ArrayType (
123
- $ inputArrayType -> getKeyType (),
115
+ $ inputArgType -> getIterableKeyType (),
124
116
$ addEmpty ? TypeCombinator::addNull ($ valueType ) : $ valueType ,
125
117
);
126
118
@@ -148,7 +140,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
148
140
}
149
141
} else {
150
142
$ optionalKeys = $ filterKeysList ;
151
- $ inputTypesMap = array_fill_keys ($ optionalKeys , $ inputArrayType -> getItemType ());
143
+ $ inputTypesMap = array_fill_keys ($ optionalKeys , $ inputArgType -> getIterableValueType ());
152
144
}
153
145
}
154
146
@@ -184,21 +176,23 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
184
176
/** @return array{?Type, ?Type} */
185
177
public function fetchFilter (Type $ type ): array
186
178
{
187
- $ constantType = $ type ->getConstantArrays ()[0 ] ?? null ;
179
+ if (!$ type ->isArray ()->yes ()) {
180
+ return [$ type , null ];
181
+ }
188
182
189
- if ($ constantType === null ) {
183
+ $ filterKey = new ConstantStringType ('filter ' );
184
+ if (!$ type ->hasOffsetValueType ($ filterKey )->yes ()) {
190
185
return [$ type , null ];
191
186
}
192
187
188
+ $ filterOffsetType = $ type ->getOffsetValueType ($ filterKey );
193
189
$ filterType = null ;
194
- foreach ($ constantType ->getKeyTypes () as $ keyType ) {
195
- if ($ keyType ->getValue () === 'filter ' ) {
196
- $ filterType = $ constantType ->getOffsetValueType ($ keyType )->getConstantScalarTypes ()[0 ] ?? null ;
197
- break ;
198
- }
190
+
191
+ if (count ($ filterOffsetType ->getConstantScalarTypes ()) > 0 ) {
192
+ $ filterType = TypeCombinator::union (...$ filterOffsetType ->getConstantScalarTypes ());
199
193
}
200
194
201
- return [$ filterType , $ constantType ];
195
+ return [$ filterType , $ type ];
202
196
}
203
197
204
198
}
0 commit comments