|
2 | 2 |
|
3 | 3 | namespace PHPStan\Reflection; |
4 | 4 |
|
| 5 | +use PhpParser\Node\Expr\FuncCall; |
| 6 | +use PhpParser\Node\Name; |
5 | 7 | use PHPStan\Analyser\Scope; |
6 | 8 | use PHPStan\Reflection\Native\NativeParameterReflection; |
| 9 | +use PHPStan\Reflection\Php\DummyParameter; |
7 | 10 | use PHPStan\TrinaryLogic; |
| 11 | +use PHPStan\Type\CallableType; |
| 12 | +use PHPStan\Type\Constant\ConstantIntegerType; |
8 | 13 | use PHPStan\Type\Generic\TemplateTypeMap; |
9 | 14 | use PHPStan\Type\MixedType; |
10 | 15 | use PHPStan\Type\TypeCombinator; |
@@ -43,6 +48,87 @@ public static function selectFromArgs( |
43 | 48 | { |
44 | 49 | $types = []; |
45 | 50 | $unpack = false; |
| 51 | + if (count($args) > 0 && count($parametersAcceptors) > 0) { |
| 52 | + $functionName = null; |
| 53 | + $argParent = $args[0]->getAttribute('parent'); |
| 54 | + if ($argParent instanceof FuncCall && $argParent->name instanceof Name) { |
| 55 | + $functionName = $argParent->name->toLowerString(); |
| 56 | + } |
| 57 | + if ( |
| 58 | + $functionName === 'array_map' |
| 59 | + && isset($args[1]) |
| 60 | + ) { |
| 61 | + $acceptor = $parametersAcceptors[0]; |
| 62 | + $parameters = $acceptor->getParameters(); |
| 63 | + $parameters[0] = new NativeParameterReflection( |
| 64 | + $parameters[0]->getName(), |
| 65 | + $parameters[0]->isOptional(), |
| 66 | + new CallableType([ |
| 67 | + new DummyParameter('item', $scope->getType($args[1]->value)->getIterableValueType(), false, PassedByReference::createNo(), false, null), |
| 68 | + ], new MixedType(), false), |
| 69 | + $parameters[0]->passedByReference(), |
| 70 | + $parameters[0]->isVariadic(), |
| 71 | + $parameters[0]->getDefaultValue() |
| 72 | + ); |
| 73 | + $parametersAcceptors = [ |
| 74 | + new FunctionVariant( |
| 75 | + $acceptor->getTemplateTypeMap(), |
| 76 | + $acceptor->getResolvedTemplateTypeMap(), |
| 77 | + $parameters, |
| 78 | + $acceptor->isVariadic(), |
| 79 | + $acceptor->getReturnType() |
| 80 | + ), |
| 81 | + ]; |
| 82 | + } |
| 83 | + |
| 84 | + if ( |
| 85 | + $functionName === 'array_filter' |
| 86 | + && isset($args[0]) |
| 87 | + ) { |
| 88 | + if (isset($args[2])) { |
| 89 | + $mode = $scope->getType($args[2]->value); |
| 90 | + if ($mode instanceof ConstantIntegerType) { |
| 91 | + if ($mode->getValue() === ARRAY_FILTER_USE_KEY) { |
| 92 | + $arrayFilterParameters = [ |
| 93 | + new DummyParameter('key', $scope->getType($args[0]->value)->getIterableKeyType(), false, PassedByReference::createNo(), false, null), |
| 94 | + ]; |
| 95 | + } elseif ($mode->getValue() === ARRAY_FILTER_USE_BOTH) { |
| 96 | + $arrayFilterParameters = [ |
| 97 | + new DummyParameter('item', $scope->getType($args[0]->value)->getIterableValueType(), false, PassedByReference::createNo(), false, null), |
| 98 | + new DummyParameter('key', $scope->getType($args[0]->value)->getIterableKeyType(), false, PassedByReference::createNo(), false, null), |
| 99 | + ]; |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + $acceptor = $parametersAcceptors[0]; |
| 105 | + $parameters = $acceptor->getParameters(); |
| 106 | + $parameters[1] = new NativeParameterReflection( |
| 107 | + $parameters[1]->getName(), |
| 108 | + $parameters[1]->isOptional(), |
| 109 | + new CallableType( |
| 110 | + $arrayFilterParameters ?? [ |
| 111 | + new DummyParameter('item', $scope->getType($args[0]->value)->getIterableValueType(), false, PassedByReference::createNo(), false, null), |
| 112 | + ], |
| 113 | + new MixedType(), |
| 114 | + false |
| 115 | + ), |
| 116 | + $parameters[1]->passedByReference(), |
| 117 | + $parameters[1]->isVariadic(), |
| 118 | + $parameters[1]->getDefaultValue() |
| 119 | + ); |
| 120 | + $parametersAcceptors = [ |
| 121 | + new FunctionVariant( |
| 122 | + $acceptor->getTemplateTypeMap(), |
| 123 | + $acceptor->getResolvedTemplateTypeMap(), |
| 124 | + $parameters, |
| 125 | + $acceptor->isVariadic(), |
| 126 | + $acceptor->getReturnType() |
| 127 | + ), |
| 128 | + ]; |
| 129 | + } |
| 130 | + } |
| 131 | + |
46 | 132 | foreach ($args as $arg) { |
47 | 133 | $type = $scope->getType($arg->value); |
48 | 134 | if ($arg->unpack) { |
|
0 commit comments