Skip to content

Commit

Permalink
Fix #2772 - add support for multiple array_map function param inference
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Feb 8, 2020
1 parent b439a57 commit 5f4d797
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 22 deletions.
46 changes: 24 additions & 22 deletions src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ protected static function checkFunctionArguments(
return;
}

if ($method_id === 'array_map' && count($args) === 2) {
if ($method_id === 'array_map') {
$args = array_reverse($args, true);
}

Expand Down Expand Up @@ -453,26 +453,29 @@ protected static function checkFunctionArguments(
&& $param->type
&& !$arg->value->getDocComment()
) {
if (count($args) === 2
&& (($argument_offset === 1 && $method_id === 'array_filter')
|| ($argument_offset === 0 && $method_id === 'array_map'))
if (($argument_offset === 1 && $method_id === 'array_filter' && count($args) === 2)
|| ($argument_offset === 0 && $method_id === 'array_map' && count($args) >= 2)
) {
$function_like_params = [];

foreach ($template_result->generic_params as $template_name => $_) {
$function_like_params[] = new \Psalm\Storage\FunctionLikeParameter(
'function',
false,
new Type\Union([
new Type\Atomic\TTemplateParam(
$template_name,
Type::getMixed(),
$method_id
)
])
);
}

$replaced_type = new Type\Union([
new Type\Atomic\TCallable(
'callable',
[
new \Psalm\Storage\FunctionLikeParameter(
'function',
false,
new Type\Union([
new Type\Atomic\TTemplateParam(
'ArrayValue',
Type::getMixed(),
$method_id
)
])
)
]
array_reverse($function_like_params)
)
]);
} else {
Expand Down Expand Up @@ -547,24 +550,23 @@ protected static function checkFunctionArguments(
$context->inside_call = false;
}

if (count($args) === 2
&& (($argument_offset === 0 && $method_id === 'array_filter')
|| ($argument_offset === 1 && $method_id === 'array_map'))
if (($argument_offset === 0 && $method_id === 'array_filter' && count($args) === 2)
|| ($argument_offset > 0 && $method_id === 'array_map' && count($args) >= 2)
) {
$generic_param_type = new Type\Union([
new Type\Atomic\TArray([
Type::getArrayKey(),
new Type\Union([
new Type\Atomic\TTemplateParam(
'ArrayValue',
'ArrayValue' . $argument_offset,
Type::getMixed(),
$method_id
)
])
])
]);

$template_types = ['ArrayValue' => [$method_id => [Type::getMixed()]]];
$template_types = ['ArrayValue' . $argument_offset => [$method_id => [Type::getMixed()]]];

$replace_template_result = new \Psalm\Internal\Type\TemplateResult(
$template_types,
Expand Down
7 changes: 7 additions & 0 deletions tests/ArrayFunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,13 @@ function takesString(string $string): void {}
takesString($a[0]);
array_map("takesString", $a);',
],
'arrayMapExplicitZip' => [
'<?php
$as = ["key"];
$bs = ["value"];
return array_map(fn ($a, $b) => [$a => $b], $as, $bs);'
],
];
}

Expand Down

0 comments on commit 5f4d797

Please sign in to comment.