1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-10 23:18:40 +01:00
psalm/src/Psalm/Storage/Assertion.php

105 lines
3.3 KiB
PHP
Raw Normal View History

<?php
namespace Psalm\Storage;
2021-12-03 20:11:20 +01:00
use Psalm\Codebase;
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;
use function array_map;
use function implode;
2021-12-03 21:07:25 +01:00
use function is_string;
use function str_replace;
class Assertion
{
/**
* @var array<int, array<int, string>> the rule being asserted
*/
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
* @param array<int, array<int, string>> $rule
*/
public function __construct($var_id, array $rule)
{
$this->rule = $rule;
$this->var_id = $var_id;
}
/**
* @param array<string, array<string, non-empty-list<TemplateBound>>> $inferred_lower_bounds
*/
public function getUntemplatedCopy(
array $inferred_lower_bounds,
?string $this_var_id,
2021-12-03 20:11:20 +01:00
?Codebase $codebase
): self {
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,
array_map(
/**
* @param array<int, string> $rules
2020-10-17 18:36:44 +02:00
*
* @return array{0: string}
*/
function (array $rules) use ($inferred_lower_bounds, $codebase): array {
$first_rule = $rules[0];
if ($inferred_lower_bounds) {
2021-12-03 20:11:20 +01:00
$rule_tokens = TypeTokenizer::tokenize($first_rule);
$substitute = false;
foreach ($rule_tokens as &$rule_token) {
if (isset($inferred_lower_bounds[$rule_token[0]])) {
foreach ($inferred_lower_bounds[$rule_token[0]] as $lower_bounds) {
$substitute = true;
$bound_type = TemplateStandinTypeReplacer::getMostSpecificTypeFromBounds(
$lower_bounds,
$codebase
);
$first_type = $bound_type->getSingleAtomic();
2021-12-03 20:11:20 +01:00
if ($first_type instanceof TTemplateParam) {
$rule_token[0] = $first_type->param_name;
} else {
$rule_token[0] = $first_type->getId();
}
}
}
}
if ($substitute) {
return [implode(
'',
array_map(
function ($f) {
return $f[0];
},
$rule_tokens
)
)];
}
}
return [$first_rule];
},
$this->rule
)
);
}
}