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:
commit
94f32e9718
@ -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'],
|
||||
|
@ -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'],
|
||||
|
@ -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);
|
||||
|
@ -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()]);
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user