forked from vimeo/psalm
/
ArrayRandReturnTypeProvider.php
76 lines (63 loc) · 2.24 KB
/
ArrayRandReturnTypeProvider.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?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\Union;
/**
* @internal
*/
class ArrayRandReturnTypeProvider implements FunctionReturnTypeProviderInterface
{
/**
* @return array<lowercase-string>
*/
public static function getFunctionIds(): array
{
return ['array_rand'];
}
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;
$second_arg = $call_args[1]->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::getMixed();
}
if ($first_arg_array instanceof TArray) {
$key_type = $first_arg_array->type_params[0];
} else {
$key_type = $first_arg_array->getGenericKeyType();
}
if (!$second_arg) {
return $key_type;
}
$second_arg_type = $statements_source->node_data->getType($second_arg);
if ($second_arg_type
&& $second_arg_type->isSingleIntLiteral()
&& $second_arg_type->getSingleIntLiteral()->value === 1
) {
return $key_type;
}
$arr_type = Type::getList($key_type);
if ($second_arg_type && $second_arg_type->isSingleIntLiteral()) {
return $arr_type;
}
return Type::combineUnionTypes($key_type, $arr_type);
}
}