Skip to content

Commit

Permalink
Improve accuracy of array_filter
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Sep 14, 2020
1 parent 1b3fbeb commit f83c96e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,52 @@ public static function getFunctionReturnType(
} else {
$inner_type = $first_arg_array->getGenericValueType();
$key_type = $first_arg_array->getGenericKeyType();

if (!isset($call_args[1]) && !$first_arg_array->previous_value_type) {
$had_one = count($first_arg_array->properties) === 1;

$first_arg_array = clone $first_arg_array;

$new_properties = \array_filter(
array_map(
function ($keyed_type) use ($statements_source, $context) {
$prev_keyed_type = $keyed_type;

$keyed_type = \Psalm\Internal\Type\AssertionReconciler::reconcile(
'!falsy',
clone $keyed_type,
'',
$statements_source,
$context->inside_loop,
[],
null,
$statements_source->getSuppressedIssues()
);

$keyed_type->possibly_undefined = ($prev_keyed_type->hasInt()
&& !$prev_keyed_type->hasLiteralInt())
|| $prev_keyed_type->hasFloat()
|| $prev_keyed_type->getId() !== $keyed_type->getId();

return $keyed_type;
},
$first_arg_array->properties
),
function ($keyed_type) {
return !$keyed_type->isEmpty();
}
);

if (!$new_properties) {
return Type::getEmptyArray();
}

$first_arg_array->properties = $new_properties;

$first_arg_array->is_list = $first_arg_array->is_list && $had_one;

return new Type\Union([$first_arg_array]);
}
}

if (!isset($call_args[1])) {
Expand Down Expand Up @@ -97,7 +143,20 @@ public static function getFunctionReturnType(
if ($key_type->getLiteralInts()) {
$key_type->addType(new Type\Atomic\TInt);
}
} elseif (!isset($call_args[2])) {

if (!$inner_type->getAtomicTypes()) {
return Type::getEmptyArray();
}

return new Type\Union([
new Type\Atomic\TArray([
$key_type,
$inner_type,
]),
]);
}

if (!isset($call_args[2])) {
$function_call_arg = $call_args[1];

if ($function_call_arg->value instanceof PhpParser\Node\Scalar\String_
Expand Down
8 changes: 4 additions & 4 deletions tests/ArrayFunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public function providerValidCodeParse(): iterable
return [
'arrayFilter' => [
'<?php
$d = array_filter(["a" => 5, "b" => 12, "c" => null]);
$d = array_filter(["a" => rand(0, 10), "b" => rand(0, 10), "c" => null]);
$e = array_filter(
["a" => 5, "b" => 12, "c" => null],
["a" => rand(0, 10), "b" => rand(0, 10), "c" => null],
function(?int $i): bool {
return true;
}
);',
'assertions' => [
'$d' => 'array<string, int>',
'$d' => 'array{a?: int, b?: int}',
'$e' => 'array<string, int|null>',
],
],
Expand Down Expand Up @@ -2011,7 +2011,7 @@ function foo($data): void {
function ints(array $ints) : void {}
$brr = array_filter([2,3,0,4,5]);
ints($brr);',
'error_message' => 'ArgumentTypeCoercion - src' . DIRECTORY_SEPARATOR . 'somefile.php:5:26 - Argument 1 of ints expects list<int>, parent type array<int, int(2)|int(3)|int(4)|int(5)> provided',
'error_message' => 'InvalidArgument',
],
'usortOneParamInvalid' => [
'<?php
Expand Down

0 comments on commit f83c96e

Please sign in to comment.