@@ -87,8 +87,10 @@ public static function selectFromArgs(
8787 $ arrayMapArgs = $ args [0 ]->value ->getAttribute (ArrayMapArgVisitor::ATTRIBUTE_NAME );
8888 if ($ arrayMapArgs !== null ) {
8989 $ callbackParameters = [];
90+ $ nativeCallbackParameters = [];
9091 foreach ($ arrayMapArgs as $ arg ) {
9192 $ argType = $ scope ->getType ($ arg ->value );
93+ $ nativeArgType = $ scope ->getNativeType ($ arg ->value );
9294 if ($ arg ->unpack ) {
9395 $ constantArrays = $ argType ->getConstantArrays ();
9496 if (count ($ constantArrays ) > 0 ) {
@@ -99,35 +101,34 @@ public static function selectFromArgs(
99101 }
100102 }
101103 }
104+ $ nativeConstantArrays = $ nativeArgType ->getConstantArrays ();
105+ if (count ($ nativeConstantArrays ) > 0 ) {
106+ foreach ($ nativeConstantArrays as $ constantArray ) {
107+ $ valueTypes = $ constantArray ->getValueTypes ();
108+ foreach ($ valueTypes as $ valueType ) {
109+ $ nativeCallbackParameters [] = new DummyParameter ('item ' , $ scope ->getIterableValueType ($ valueType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
110+ }
111+ }
112+ }
102113 } else {
103114 $ callbackParameters [] = new DummyParameter ('item ' , $ scope ->getIterableValueType ($ argType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
115+ $ nativeCallbackParameters [] = new DummyParameter ('item ' , $ scope ->getIterableValueType ($ nativeArgType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
104116 }
105117 }
106118
107119 $ acceptor = $ parametersAcceptors [0 ];
108120 $ parameters = $ acceptor ->getParameters ();
109121 if (isset ($ parameters [0 ])) {
110- $ parameters [0 ] = new NativeParameterReflection (
111- $ parameters [0 ]->getName (),
112- $ parameters [0 ]->isOptional (),
113- new UnionType ([
114- new CallableType ($ callbackParameters , new MixedType (), false ),
115- new NullType (),
116- ]),
117- $ parameters [0 ]->passedByReference (),
118- $ parameters [0 ]->isVariadic (),
119- $ parameters [0 ]->getDefaultValue (),
120- );
121- $ parametersAcceptors = [
122- new FunctionVariant (
123- $ acceptor ->getTemplateTypeMap (),
124- $ acceptor ->getResolvedTemplateTypeMap (),
125- $ parameters ,
126- $ acceptor ->isVariadic (),
127- $ acceptor ->getReturnType (),
128- $ acceptor instanceof ExtendedParametersAcceptor ? $ acceptor ->getCallSiteVarianceMap () : TemplateTypeVarianceMap::createEmpty (),
129- ),
130- ];
122+ $ callableType = new UnionType ([
123+ new CallableType ($ callbackParameters , new MixedType (), false ),
124+ new NullType (),
125+ ]);
126+ $ nativeCallableType = new UnionType ([
127+ new CallableType ($ nativeCallbackParameters , new MixedType (), false ),
128+ new NullType (),
129+ ]);
130+ $ parameters [0 ] = self ::createExtendedParameter ($ parameters [0 ], $ callableType , $ nativeCallableType );
131+ $ parametersAcceptors = [self ::createModifiedAcceptor ($ acceptor , $ parameters )];
131132 }
132133 }
133134
@@ -228,52 +229,58 @@ public static function selectFromArgs(
228229 }
229230
230231 if ((bool ) $ args [0 ]->getAttribute (ArrayFilterArgVisitor::ATTRIBUTE_NAME )) {
232+ $ arrayFilterParameters = null ;
233+ $ nativeArrayFilterParameters = null ;
231234 if (isset ($ args [2 ])) {
232235 $ mode = $ scope ->getType ($ args [2 ]->value );
233236 if ($ mode instanceof ConstantIntegerType) {
234237 if ($ mode ->getValue () === ARRAY_FILTER_USE_KEY ) {
235238 $ arrayFilterParameters = [
236239 new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
237240 ];
241+ $ nativeArrayFilterParameters = [
242+ new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ scope ->getNativeType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
243+ ];
238244 } elseif ($ mode ->getValue () === ARRAY_FILTER_USE_BOTH ) {
239245 $ arrayFilterParameters = [
240246 new DummyParameter ('item ' , $ scope ->getIterableValueType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
241247 new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
242248 ];
249+ $ nativeArrayFilterParameters = [
250+ new DummyParameter ('item ' , $ scope ->getIterableValueType ($ scope ->getNativeType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
251+ new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ scope ->getNativeType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
252+ ];
243253 }
244254 }
245255 }
246256
247257 $ acceptor = $ parametersAcceptors [0 ];
248258 $ parameters = $ acceptor ->getParameters ();
249259 if (isset ($ parameters [1 ])) {
250- $ parameters [1 ] = new NativeParameterReflection (
251- $ parameters [1 ]->getName (),
252- $ parameters [1 ]->isOptional (),
253- new UnionType ([
254- new CallableType (
255- $ arrayFilterParameters ?? [
256- new DummyParameter ('item ' , $ scope ->getIterableValueType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
257- ],
258- new BooleanType (),
259- false ,
260- ),
261- new NullType (),
262- ]),
263- $ parameters [1 ]->passedByReference (),
264- $ parameters [1 ]->isVariadic (),
265- $ parameters [1 ]->getDefaultValue (),
266- );
267- $ parametersAcceptors = [
268- new FunctionVariant (
269- $ acceptor ->getTemplateTypeMap (),
270- $ acceptor ->getResolvedTemplateTypeMap (),
271- $ parameters ,
272- $ acceptor ->isVariadic (),
273- $ acceptor ->getReturnType (),
274- $ acceptor instanceof ExtendedParametersAcceptor ? $ acceptor ->getCallSiteVarianceMap () : TemplateTypeVarianceMap::createEmpty (),
260+ $ arrayArgType = $ scope ->getType ($ args [0 ]->value );
261+ $ nativeArrayArgType = $ scope ->getNativeType ($ args [0 ]->value );
262+ $ callableType = new UnionType ([
263+ new CallableType (
264+ $ arrayFilterParameters ?? [
265+ new DummyParameter ('item ' , $ scope ->getIterableValueType ($ arrayArgType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
266+ ],
267+ new BooleanType (),
268+ false ,
275269 ),
276- ];
270+ new NullType (),
271+ ]);
272+ $ nativeCallableType = new UnionType ([
273+ new CallableType (
274+ $ nativeArrayFilterParameters ?? [
275+ new DummyParameter ('item ' , $ scope ->getIterableValueType ($ nativeArrayArgType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
276+ ],
277+ new BooleanType (),
278+ false ,
279+ ),
280+ new NullType (),
281+ ]);
282+ $ parameters [1 ] = self ::createExtendedParameter ($ parameters [1 ], $ callableType , $ nativeCallableType );
283+ $ parametersAcceptors = [self ::createModifiedAcceptor ($ acceptor , $ parameters )];
277284 }
278285 }
279286
@@ -307,35 +314,28 @@ public static function selectFromArgs(
307314 }
308315
309316 if ((bool ) $ args [0 ]->getAttribute (ArrayWalkArgVisitor::ATTRIBUTE_NAME )) {
317+ $ arrayArgType = $ scope ->getType ($ args [0 ]->value );
318+ $ nativeArrayArgType = $ scope ->getNativeType ($ args [0 ]->value );
310319 $ arrayWalkParameters = [
311- new DummyParameter ('item ' , $ scope ->getIterableValueType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createReadsArgument (), variadic: false , defaultValue: null ),
312- new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ scope ->getType ($ args [0 ]->value )), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
320+ new DummyParameter ('item ' , $ scope ->getIterableValueType ($ arrayArgType ), optional: false , passedByReference: PassedByReference::createReadsArgument (), variadic: false , defaultValue: null ),
321+ new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ arrayArgType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
322+ ];
323+ $ nativeArrayWalkParameters = [
324+ new DummyParameter ('item ' , $ scope ->getIterableValueType ($ nativeArrayArgType ), optional: false , passedByReference: PassedByReference::createReadsArgument (), variadic: false , defaultValue: null ),
325+ new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ nativeArrayArgType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
313326 ];
314327 if (isset ($ args [2 ])) {
315328 $ arrayWalkParameters [] = new DummyParameter ('arg ' , $ scope ->getType ($ args [2 ]->value ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
329+ $ nativeArrayWalkParameters [] = new DummyParameter ('arg ' , $ scope ->getNativeType ($ args [2 ]->value ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
316330 }
317331
318332 $ acceptor = $ parametersAcceptors [0 ];
319333 $ parameters = $ acceptor ->getParameters ();
320334 if (isset ($ parameters [1 ])) {
321- $ parameters [1 ] = new NativeParameterReflection (
322- $ parameters [1 ]->getName (),
323- $ parameters [1 ]->isOptional (),
324- new CallableType ($ arrayWalkParameters , new MixedType (), false ),
325- $ parameters [1 ]->passedByReference (),
326- $ parameters [1 ]->isVariadic (),
327- $ parameters [1 ]->getDefaultValue (),
328- );
329- $ parametersAcceptors = [
330- new FunctionVariant (
331- $ acceptor ->getTemplateTypeMap (),
332- $ acceptor ->getResolvedTemplateTypeMap (),
333- $ parameters ,
334- $ acceptor ->isVariadic (),
335- $ acceptor ->getReturnType (),
336- $ acceptor instanceof ExtendedParametersAcceptor ? $ acceptor ->getCallSiteVarianceMap () : TemplateTypeVarianceMap::createEmpty (),
337- ),
338- ];
335+ $ callableType = new CallableType ($ arrayWalkParameters , new MixedType (), false );
336+ $ nativeCallableType = new CallableType ($ nativeArrayWalkParameters , new MixedType (), false );
337+ $ parameters [1 ] = self ::createExtendedParameter ($ parameters [1 ], $ callableType , $ nativeCallableType );
338+ $ parametersAcceptors = [self ::createModifiedAcceptor ($ acceptor , $ parameters )];
339339 }
340340 }
341341
@@ -344,31 +344,25 @@ public static function selectFromArgs(
344344 $ parameters = $ acceptor ->getParameters ();
345345 if (isset ($ parameters [1 ])) {
346346 $ argType = $ scope ->getType ($ args [0 ]->value );
347- $ parameters [1 ] = new NativeParameterReflection (
348- $ parameters [1 ]->getName (),
349- $ parameters [1 ]->isOptional (),
350- new CallableType (
351- [
352- new DummyParameter ('value ' , $ scope ->getIterableValueType ($ argType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
353- new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ argType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
354- ],
355- new BooleanType (),
356- false ,
357- ),
358- $ parameters [1 ]->passedByReference (),
359- $ parameters [1 ]->isVariadic (),
360- $ parameters [1 ]->getDefaultValue (),
347+ $ nativeArgType = $ scope ->getNativeType ($ args [0 ]->value );
348+ $ callableType = new CallableType (
349+ [
350+ new DummyParameter ('value ' , $ scope ->getIterableValueType ($ argType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
351+ new DummyParameter ('key ' , $ scope ->getIterableKeyType ($ argType ), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null ),
352+ ],
353+ new BooleanType (),
354+ false ,
361355 );
362- $ parametersAcceptors = [
363- new FunctionVariant (
364- $ acceptor -> getTemplateTypeMap ( ),
365- $ acceptor -> getResolvedTemplateTypeMap ( ),
366- $ parameters ,
367- $ acceptor -> isVariadic (),
368- $ acceptor -> getReturnType () ,
369- $ acceptor instanceof ExtendedParametersAcceptor ? $ acceptor -> getCallSiteVarianceMap () : TemplateTypeVarianceMap:: createEmpty (),
370- ),
371- ];
356+ $ nativeCallableType = new CallableType (
357+ [
358+ new DummyParameter ( ' value ' , $ scope -> getIterableValueType ( $ nativeArgType ), optional: false , passedByReference: PassedByReference:: createNo (), variadic: false , defaultValue: null ),
359+ new DummyParameter ( ' key ' , $ scope -> getIterableKeyType ( $ nativeArgType ), optional: false , passedByReference: PassedByReference:: createNo (), variadic: false , defaultValue: null ),
360+ ] ,
361+ new BooleanType (),
362+ false ,
363+ );
364+ $ parameters [ 1 ] = self :: createExtendedParameter ( $ parameters [ 1 ], $ callableType , $ nativeCallableType );
365+ $ parametersAcceptors = [ self :: createModifiedAcceptor ( $ acceptor , $ parameters ) ];
372366 }
373367 }
374368
@@ -1238,4 +1232,50 @@ private static function getCurlOptValueType(int $curlOpt): ?Type
12381232 return null ;
12391233 }
12401234
1235+ private static function createExtendedParameter (ParameterReflection $ original , Type $ type , Type $ nativeType ): ExtendedDummyParameter
1236+ {
1237+ return new ExtendedDummyParameter (
1238+ $ original ->getName (),
1239+ $ type ,
1240+ $ original ->isOptional (),
1241+ $ original ->passedByReference (),
1242+ $ original ->isVariadic (),
1243+ $ original ->getDefaultValue (),
1244+ $ nativeType ,
1245+ $ type ,
1246+ $ original instanceof ExtendedParameterReflection ? $ original ->getOutType () : null ,
1247+ $ original instanceof ExtendedParameterReflection ? $ original ->isImmediatelyInvokedCallable () : TrinaryLogic::createMaybe (),
1248+ $ original instanceof ExtendedParameterReflection ? $ original ->getClosureThisType () : null ,
1249+ $ original instanceof ExtendedParameterReflection ? $ original ->getAttributes () : [],
1250+ );
1251+ }
1252+
1253+ /**
1254+ * @param list<ParameterReflection> $parameters
1255+ */
1256+ private static function createModifiedAcceptor (ParametersAcceptor $ acceptor , array $ parameters ): ParametersAcceptor
1257+ {
1258+ if ($ acceptor instanceof ExtendedParametersAcceptor) {
1259+ return new ExtendedFunctionVariant (
1260+ $ acceptor ->getTemplateTypeMap (),
1261+ $ acceptor ->getResolvedTemplateTypeMap (),
1262+ array_map (static fn (ParameterReflection $ p ): ExtendedParameterReflection => $ p instanceof ExtendedParameterReflection ? $ p : self ::wrapParameter ($ p ), $ parameters ),
1263+ $ acceptor ->isVariadic (),
1264+ $ acceptor ->getReturnType (),
1265+ $ acceptor ->getPhpDocReturnType (),
1266+ $ acceptor ->getNativeReturnType (),
1267+ $ acceptor ->getCallSiteVarianceMap (),
1268+ );
1269+ }
1270+
1271+ return new FunctionVariant (
1272+ $ acceptor ->getTemplateTypeMap (),
1273+ $ acceptor ->getResolvedTemplateTypeMap (),
1274+ $ parameters ,
1275+ $ acceptor ->isVariadic (),
1276+ $ acceptor ->getReturnType (),
1277+ TemplateTypeVarianceMap::createEmpty (),
1278+ );
1279+ }
1280+
12411281}
0 commit comments