/
InArrayReturnTypeProvider.php
82 lines (65 loc) · 2.49 KB
/
InArrayReturnTypeProvider.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
77
78
79
80
81
82
<?php
namespace Psalm\Internal\Provider\ReturnTypeProvider;
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
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\TList;
class InArrayReturnTypeProvider implements FunctionReturnTypeProviderInterface
{
/**
* @return array<lowercase-string>
*/
public static function getFunctionIds(): array
{
return ['in_array'];
}
public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): Type\Union
{
$call_args = $event->getCallArgs();
$bool = Type::getBool();
if (!isset($call_args[0]) || !isset($call_args[1])) {
return $bool;
}
$needle_type = $event->getStatementsSource()->getNodeTypeProvider()->getType($call_args[0]->value);
$haystack_type = $event->getStatementsSource()->getNodeTypeProvider()->getType($call_args[1]->value);
if ($needle_type === null || $haystack_type === null) {
return $bool;
}
$false = Type::getFalse();
$false->from_docblock = $bool->from_docblock = $needle_type->from_docblock || $haystack_type->from_docblock;
if (!isset($call_args[2])) {
return $bool;
}
$strict_type = $event->getStatementsSource()->getNodeTypeProvider()->getType($call_args[2]->value);
if ($strict_type === null || !$strict_type->isTrue()) {
return $bool;
}
/**
* @var TKeyedArray|TArray|TList|null
*/
$array_arg_type = ($types = $haystack_type->getAtomicTypes()) && isset($types['array'])
? $types['array']
: null;
if ($array_arg_type instanceof TKeyedArray) {
$array_arg_type = $array_arg_type->getGenericArrayType();
}
if ($array_arg_type instanceof TList) {
$array_arg_type = new TArray([Type::getInt(), $array_arg_type->type_param]);
}
if (!$array_arg_type instanceof TArray) {
return $bool;
}
$haystack_item_type = $array_arg_type->type_params[1];
if (UnionTypeComparator::canExpressionTypesBeIdentical(
$event->getStatementsSource()->getCodebase(),
$needle_type,
$haystack_item_type
)) {
return $bool;
}
return $false;
}
}