2018-02-23 21:39:33 +01:00
|
|
|
<?php
|
|
|
|
namespace Psalm\Storage;
|
|
|
|
|
2021-12-03 20:11:20 +01:00
|
|
|
use Psalm\Codebase;
|
2021-07-11 18:03:21 +02:00
|
|
|
use Psalm\Internal\Type\TemplateBound;
|
|
|
|
use Psalm\Internal\Type\TemplateStandinTypeReplacer;
|
2021-12-03 20:11:20 +01:00
|
|
|
use Psalm\Internal\Type\TypeTokenizer;
|
|
|
|
use Psalm\Type\Atomic\TTemplateParam;
|
2021-07-11 18:03:21 +02:00
|
|
|
|
2019-06-26 22:52:29 +02:00
|
|
|
use function array_map;
|
|
|
|
use function implode;
|
2021-12-03 21:07:25 +01:00
|
|
|
use function is_string;
|
|
|
|
use function str_replace;
|
2019-06-26 22:52:29 +02:00
|
|
|
|
2018-02-23 21:39:33 +01:00
|
|
|
class Assertion
|
|
|
|
{
|
|
|
|
/**
|
2018-05-13 01:38:43 +02:00
|
|
|
* @var array<int, array<int, string>> the rule being asserted
|
2018-02-23 21:39:33 +01:00
|
|
|
*/
|
|
|
|
public $rule;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var int|string the id of the property/variable, or
|
|
|
|
* the parameter offset of the affected arg
|
|
|
|
*/
|
|
|
|
public $var_id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string|int $var_id
|
2018-05-13 01:38:43 +02:00
|
|
|
* @param array<int, array<int, string>> $rule
|
2018-02-23 21:39:33 +01:00
|
|
|
*/
|
2019-07-04 21:05:55 +02:00
|
|
|
public function __construct($var_id, array $rule)
|
2018-02-23 21:39:33 +01:00
|
|
|
{
|
|
|
|
$this->rule = $rule;
|
|
|
|
$this->var_id = $var_id;
|
|
|
|
}
|
2019-01-23 05:42:54 +01:00
|
|
|
|
|
|
|
/**
|
2021-07-11 18:03:21 +02:00
|
|
|
* @param array<string, array<string, non-empty-list<TemplateBound>>> $inferred_lower_bounds
|
2019-01-23 05:42:54 +01:00
|
|
|
*/
|
2021-07-11 18:03:21 +02:00
|
|
|
public function getUntemplatedCopy(
|
|
|
|
array $inferred_lower_bounds,
|
|
|
|
?string $this_var_id,
|
2021-12-03 20:11:20 +01:00
|
|
|
?Codebase $codebase
|
2021-12-05 18:51:26 +01:00
|
|
|
): self {
|
2019-01-23 05:42:54 +01:00
|
|
|
return new Assertion(
|
2021-12-03 21:07:25 +01:00
|
|
|
is_string($this->var_id) && $this_var_id
|
|
|
|
? str_replace('$this->', $this_var_id . '->', $this->var_id)
|
2019-12-30 16:01:31 +01:00
|
|
|
: $this->var_id,
|
2019-01-23 05:42:54 +01:00
|
|
|
array_map(
|
|
|
|
/**
|
|
|
|
* @param array<int, string> $rules
|
2020-10-17 18:36:44 +02:00
|
|
|
*
|
|
|
|
* @return array{0: string}
|
2019-01-23 05:42:54 +01:00
|
|
|
*/
|
2021-12-05 18:51:26 +01:00
|
|
|
function (array $rules) use ($inferred_lower_bounds, $codebase): array {
|
2019-01-23 05:42:54 +01:00
|
|
|
$first_rule = $rules[0];
|
|
|
|
|
2021-07-10 20:08:09 +02:00
|
|
|
if ($inferred_lower_bounds) {
|
2021-12-03 20:11:20 +01:00
|
|
|
$rule_tokens = TypeTokenizer::tokenize($first_rule);
|
2019-06-23 05:30:40 +02:00
|
|
|
|
|
|
|
$substitute = false;
|
|
|
|
|
2019-01-23 05:42:54 +01:00
|
|
|
foreach ($rule_tokens as &$rule_token) {
|
2021-07-10 20:08:09 +02:00
|
|
|
if (isset($inferred_lower_bounds[$rule_token[0]])) {
|
2021-07-11 18:03:21 +02:00
|
|
|
foreach ($inferred_lower_bounds[$rule_token[0]] as $lower_bounds) {
|
2019-06-23 05:30:40 +02:00
|
|
|
$substitute = true;
|
2019-07-21 07:40:19 +02:00
|
|
|
|
2021-07-11 18:03:21 +02:00
|
|
|
$bound_type = TemplateStandinTypeReplacer::getMostSpecificTypeFromBounds(
|
|
|
|
$lower_bounds,
|
|
|
|
$codebase
|
|
|
|
);
|
|
|
|
|
2021-12-11 20:44:34 +01:00
|
|
|
$first_type = $bound_type->getSingleAtomic();
|
2019-12-29 00:37:55 +01:00
|
|
|
|
2021-12-03 20:11:20 +01:00
|
|
|
if ($first_type instanceof TTemplateParam) {
|
2019-12-29 00:37:55 +01:00
|
|
|
$rule_token[0] = $first_type->param_name;
|
|
|
|
} else {
|
2021-12-06 00:25:40 +01:00
|
|
|
$rule_token[0] = $first_type->getId();
|
2019-12-29 00:37:55 +01:00
|
|
|
}
|
2019-03-22 20:59:10 +01:00
|
|
|
}
|
2019-01-23 05:42:54 +01:00
|
|
|
}
|
|
|
|
}
|
2019-06-23 05:30:40 +02:00
|
|
|
|
|
|
|
if ($substitute) {
|
|
|
|
return [implode(
|
|
|
|
'',
|
|
|
|
array_map(
|
|
|
|
function ($f) {
|
|
|
|
return $f[0];
|
|
|
|
},
|
|
|
|
$rule_tokens
|
|
|
|
)
|
|
|
|
)];
|
|
|
|
}
|
2019-01-23 05:42:54 +01:00
|
|
|
}
|
|
|
|
|
2019-06-23 05:30:40 +02:00
|
|
|
return [$first_rule];
|
2019-01-23 05:42:54 +01:00
|
|
|
},
|
|
|
|
$this->rule
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2018-02-23 21:39:33 +01:00
|
|
|
}
|