mirror of
https://github.com/danog/phpdoc-parser.git
synced 2025-01-22 22:01:36 +01:00
type aliases: support @phpstan-type and @psalm-type tags
This commit is contained in:
parent
2ce4c66233
commit
2d862ef746
@ -238,6 +238,20 @@ class PhpDocNode implements Node
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return TypeAliasTagValueNode[]
|
||||
*/
|
||||
public function getTypeAliasTagValues(string $tagName = '@phpstan-type'): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof TypeAliasTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "/**\n * " . implode("\n * ", $this->children) . '*/';
|
||||
|
28
src/Ast/PhpDoc/TypeAliasTagValueNode.php
Normal file
28
src/Ast/PhpDoc/TypeAliasTagValueNode.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class TypeAliasTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $alias;
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
public function __construct(string $alias, TypeNode $type)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("{$this->alias} {$this->type}");
|
||||
}
|
||||
|
||||
}
|
@ -189,6 +189,11 @@ class PhpDocParser
|
||||
$tagValue = $this->parseExtendsTagValue('@use', $tokens);
|
||||
break;
|
||||
|
||||
case '@phpstan-type':
|
||||
case '@psalm-type':
|
||||
$tagValue = $this->parseTypeAliasTagValue($tokens);
|
||||
break;
|
||||
|
||||
default:
|
||||
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
|
||||
break;
|
||||
@ -364,6 +369,19 @@ class PhpDocParser
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
private function parseTypeAliasTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasTagValueNode
|
||||
{
|
||||
$alias = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
|
||||
// support psalm-type syntax
|
||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
|
||||
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
|
||||
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
|
||||
}
|
||||
|
||||
private function parseOptionalVariableName(TokenIterator $tokens): string
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
|
||||
|
@ -23,6 +23,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
|
||||
@ -66,6 +67,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase
|
||||
* @dataProvider provideMultiLinePhpDocData
|
||||
* @dataProvider provideTemplateTagsData
|
||||
* @dataProvider provideExtendsTagsData
|
||||
* @dataProvider provideTypeAliasTagsData
|
||||
* @dataProvider provideRealWorldExampleData
|
||||
* @dataProvider provideDescriptionWithOrWithoutHtml
|
||||
* @param string $label
|
||||
@ -2858,6 +2860,81 @@ some text in the middle'
|
||||
];
|
||||
}
|
||||
|
||||
public function provideTypeAliasTagsData(): \Iterator
|
||||
{
|
||||
yield [
|
||||
'OK',
|
||||
'/** @phpstan-type TypeAlias string|int */',
|
||||
new PhpDocNode([
|
||||
new PhpDocTagNode(
|
||||
'@phpstan-type',
|
||||
new TypeAliasTagValueNode(
|
||||
'TypeAlias',
|
||||
new UnionTypeNode([
|
||||
new IdentifierTypeNode('string'),
|
||||
new IdentifierTypeNode('int'),
|
||||
])
|
||||
)
|
||||
),
|
||||
]),
|
||||
];
|
||||
|
||||
yield [
|
||||
'OK with psalm syntax',
|
||||
'/** @psalm-type TypeAlias=string|int */',
|
||||
new PhpDocNode([
|
||||
new PhpDocTagNode(
|
||||
'@psalm-type',
|
||||
new TypeAliasTagValueNode(
|
||||
'TypeAlias',
|
||||
new UnionTypeNode([
|
||||
new IdentifierTypeNode('string'),
|
||||
new IdentifierTypeNode('int'),
|
||||
])
|
||||
)
|
||||
),
|
||||
]),
|
||||
];
|
||||
|
||||
yield [
|
||||
'invalid without type',
|
||||
'/** @phpstan-type TypeAlias */',
|
||||
new PhpDocNode([
|
||||
new PhpDocTagNode(
|
||||
'@phpstan-type',
|
||||
new InvalidTagValueNode(
|
||||
'TypeAlias',
|
||||
new ParserException(
|
||||
'*/',
|
||||
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||
28,
|
||||
Lexer::TOKEN_IDENTIFIER
|
||||
)
|
||||
)
|
||||
),
|
||||
]),
|
||||
];
|
||||
|
||||
yield [
|
||||
'invalid empty',
|
||||
'/** @phpstan-type */',
|
||||
new PhpDocNode([
|
||||
new PhpDocTagNode(
|
||||
'@phpstan-type',
|
||||
new InvalidTagValueNode(
|
||||
'',
|
||||
new ParserException(
|
||||
'*/',
|
||||
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||
18,
|
||||
Lexer::TOKEN_IDENTIFIER
|
||||
)
|
||||
)
|
||||
),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
public function providerDebug(): \Iterator
|
||||
{
|
||||
$sample = '/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user