1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Add support for expansion of type aliases

This commit is contained in:
Brown 2020-05-15 00:15:48 -04:00
parent eaf2c94c88
commit 2d92943625
5 changed files with 68 additions and 5 deletions

View File

@ -157,7 +157,12 @@ class CommentAnalyzer
}
try {
$defined_type = TypeParser::parseTokens($var_type_tokens, null, $template_type_map ?: []);
$defined_type = TypeParser::parseTokens(
$var_type_tokens,
null,
$template_type_map ?: [],
$type_aliases ?: []
);
} catch (TypeParseTreeException $e) {
throw new DocblockParseException(
$line_parts[0] .
@ -950,7 +955,7 @@ class CommentAnalyzer
if (isset($parsed_docblock['specials']['psalm-import-type'])) {
foreach ($parsed_docblock['specials']['psalm-import-type'] as $imported_type_entry) {
/** @psalm-suppress InvalidPropertyAssignmentValue */
$info->imported_types[] = preg_split('/[\s]+/', $imported_type_entry)[0];
$info->imported_types[] = preg_split('/[\s]+/', $imported_type_entry);
}
}

View File

@ -133,7 +133,7 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
private $type_aliases = [];
/**
* @var array<string, TypeAlias>
* @var array<string, TypeAlias\InlineTypeAlias>
*/
private $classlike_type_aliases = [];
@ -602,7 +602,23 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
}
}
$classlike_storage->type_aliases = $this->classlike_type_aliases;
$classlike_storage->type_aliases = \array_map(
function (TypeAlias\InlineTypeAlias $t) {
$union = TypeParser::parseTokens(
$t->replacement_tokens,
null,
[],
$this->type_aliases
);
$union->setFromDocblock();
return new TypeAlias\ClassTypeAlias(
\array_values($union->getAtomicTypes())
);
},
$this->classlike_type_aliases
);
$this->classlike_type_aliases = [];

View File

@ -0,0 +1,18 @@
<?php
namespace Psalm\Internal\Type\TypeAlias;
class ClassTypeAlias implements \Psalm\Internal\Type\TypeAlias
{
/**
* @var list<\Psalm\Type\Atomic>
*/
public $replacement_atomic_types;
/**
* @param list<\Psalm\Type\Atomic> $replacement_atomic_types
*/
public function __construct(array $replacement_atomic_types)
{
$this->replacement_atomic_types = $replacement_atomic_types;
}
}

View File

@ -253,6 +253,30 @@ class TypeExpander
return $return_type;
}
if ($return_type instanceof Type\Atomic\TTypeAlias) {
$declaring_fq_classlike_name = $return_type->declaring_fq_classlike_name;
if ($declaring_fq_classlike_name === 'self' && $self_class) {
$declaring_fq_classlike_name = $self_class;
}
if ($evaluate_class_constants && $codebase->classOrInterfaceExists($declaring_fq_classlike_name)) {
$class_storage = $codebase->classlike_storage_provider->get($declaring_fq_classlike_name);
$type_alias_name = $return_type->alias_name;
if (isset($class_storage->type_aliases[$type_alias_name])) {
$resolved_type_alias = $class_storage->type_aliases[$type_alias_name];
if ($resolved_type_alias->replacement_atomic_types) {
return $resolved_type_alias->replacement_atomic_types;
}
}
}
return $return_type;
}
if ($return_type instanceof Type\Atomic\TKeyOfClassConstant
|| $return_type instanceof Type\Atomic\TValueOfClassConstant
) {

View File

@ -394,7 +394,7 @@ class ClassLikeStorage
public $docblock_issues = [];
/**
* @var array<string, \Psalm\Internal\Type\TypeAlias>
* @var array<string, \Psalm\Internal\Type\TypeAlias\ClassTypeAlias>
*/
public $type_aliases = [];