1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Merge pull request #9323 from othercorey/fix-array-unique

Fix array_unique callmap
This commit is contained in:
orklah 2023-03-28 20:27:18 +02:00 committed by GitHub
commit 94f32e9718
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 68 deletions

View File

@ -418,9 +418,7 @@ return [
'array_uintersect_assoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'],
'array_uintersect_uassoc' => ['array', 'array'=>'array', 'rest'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'],
'array_uintersect_uassoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'],
'array_unique' => ['array', 'array'=>'array', 'flags='=>'0'],
'array_unique\'1' => ['array<int|float|string|null>', 'array'=>'array<int|float|string|null>', 'flags='=>'1'],
'array_unique\'2' => ['array<int|float|string|bool|\Stringable|null>', 'array'=>'array<int|float|string|bool|\Stringable|null>', 'flags='=>'2|5'],
'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'],
'array_unshift' => ['int', '&rw_array'=>'array', '...values='=>'mixed'],
'array_values' => ['list<mixed>', 'array'=>'array'],
'array_walk' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'],

View File

@ -9381,9 +9381,7 @@ return [
'array_uintersect_assoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'],
'array_uintersect_uassoc' => ['array', 'array'=>'array', 'rest'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'],
'array_uintersect_uassoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'],
'array_unique' => ['array', 'array'=>'array', 'flags='=>'0'],
'array_unique\'1' => ['array<int|float|string|null>', 'array'=>'array<int|float|string|null>', 'flags='=>'1'],
'array_unique\'2' => ['array<int|float|string|bool|\Stringable|null>', 'array'=>'array<int|float|string|bool|\Stringable|null>', 'flags='=>'2|5'],
'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'],
'array_unshift' => ['int', '&rw_array'=>'array', '...values'=>'mixed'],
'array_values' => ['list<mixed>', 'array'=>'array'],
'array_walk' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'],

View File

@ -22,7 +22,6 @@ use Psalm\Internal\Provider\ReturnTypeProvider\ArrayReduceReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\ArrayReverseReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\ArraySliceReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\ArraySpliceReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\ArrayUniqueReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\BasenameReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\DirnameReturnTypeProvider;
use Psalm\Internal\Provider\ReturnTypeProvider\FilterVarReturnTypeProvider;
@ -81,7 +80,6 @@ class FunctionReturnTypeProvider
$this->registerClass(ArraySliceReturnTypeProvider::class);
$this->registerClass(ArraySpliceReturnTypeProvider::class);
$this->registerClass(ArrayReverseReturnTypeProvider::class);
$this->registerClass(ArrayUniqueReturnTypeProvider::class);
$this->registerClass(ArrayFillReturnTypeProvider::class);
$this->registerClass(ArrayFillKeysReturnTypeProvider::class);
$this->registerClass(FilterVarReturnTypeProvider::class);

View File

@ -1,60 +0,0 @@
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent;
use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TNonEmptyArray;
use Psalm\Type\Union;
/**
* @internal
*/
class ArrayUniqueReturnTypeProvider implements FunctionReturnTypeProviderInterface
{
/**
* @return array<lowercase-string>
*/
public static function getFunctionIds(): array
{
return ['array_unique'];
}
public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): Union
{
$statements_source = $event->getStatementsSource();
$call_args = $event->getCallArgs();
if (!$statements_source instanceof StatementsAnalyzer) {
return Type::getMixed();
}
$first_arg = $call_args[0]->value ?? null;
$first_arg_array = $first_arg
&& ($first_arg_type = $statements_source->node_data->getType($first_arg))
&& $first_arg_type->hasType('array')
&& ($array_atomic_type = $first_arg_type->getArray())
&& ($array_atomic_type instanceof TArray
|| $array_atomic_type instanceof TKeyedArray)
? $array_atomic_type
: null;
if (!$first_arg_array) {
return Type::getArray();
}
if ($first_arg_array instanceof TArray) {
if ($first_arg_array instanceof TNonEmptyArray) {
$first_arg_array = $first_arg_array->setCount(null);
}
return new Union([$first_arg_array]);
}
return new Union([$first_arg_array->getGenericArrayType()]);
}
}

View File

@ -129,6 +129,20 @@ function array_flip(array $array)
{
}
/**
* @psalm-template TKey as array-key
* @psalm-template TValue
* @psalm-template TArray as array<TKey, TValue>
*
* @param TArray $array
*
* @return (TArray is non-empty-array ? non-empty-array<TKey, TValue> : array<TKey, TValue>)
* @psalm-pure
*/
function array_unique(array $array, int $flags = 0)
{
}
/**
* @psalm-template TKey as array-key
* @psalm-template TArray as array<TKey, mixed>

View File

@ -2536,6 +2536,19 @@ class ArrayFunctionCallTest extends TestCase
consumeArray([makeKey() => null]);
',
],
'arrayUniquePreservesNonEmptyInput' => [
'code' => '<?php
/** @param non-empty-array<string, object> $input */
function takes_non_empty_array(array $input): void {}
takes_non_empty_array(array_unique(["test" => (object)[]]));
/** @param non-empty-array<int, object> $input */
function takes_non_empty_int_array(array $input): void {}
takes_non_empty_int_array(array_unique([(object)[]]));
',
],
];
}
@ -2809,6 +2822,24 @@ class ArrayFunctionCallTest extends TestCase
',
'error_message' => 'NamedArgumentNotAllowed',
],
'arrayUniquePreservesEmptyInput' => [
'code' => '<?php
/** @param non-empty-array<string, object> $input */
function takes_non_empty_array(array $input): void {}
takes_non_empty_array(array_unique([]));
',
'error_message' => 'InvalidArgument',
],
'arrayUniqueConvertsListToArray' => [
'code' => '<?php
/** @param non-empty-list<object> $input */
function takes_non_empty_list(array $input): void {}
takes_non_empty_list(array_unique([(object)[]]));
',
'error_message' => 'ArgumentTypeCoercion',
],
];
}
}