mirror of
https://github.com/danog/phpdoc-parser.git
synced 2024-12-02 09:28:02 +01:00
type aliases: support @phpstan-import-type and @psalm-import-type tags
This commit is contained in:
parent
2d862ef746
commit
2e17e4a907
@ -252,6 +252,20 @@ class PhpDocNode implements Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TypeAliasImportTagValueNode[]
|
||||||
|
*/
|
||||||
|
public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type'): array
|
||||||
|
{
|
||||||
|
return array_column(
|
||||||
|
array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag): bool {
|
||||||
|
return $tag->value instanceof TypeAliasImportTagValueNode;
|
||||||
|
}),
|
||||||
|
'value'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
return "/**\n * " . implode("\n * ", $this->children) . '*/';
|
return "/**\n * " . implode("\n * ", $this->children) . '*/';
|
||||||
|
34
src/Ast/PhpDoc/TypeAliasImportTagValueNode.php
Normal file
34
src/Ast/PhpDoc/TypeAliasImportTagValueNode.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||||
|
|
||||||
|
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||||
|
|
||||||
|
class TypeAliasImportTagValueNode implements PhpDocTagValueNode
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $importedAlias;
|
||||||
|
|
||||||
|
/** @var IdentifierTypeNode */
|
||||||
|
public $importedFrom;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
public $importedAs;
|
||||||
|
|
||||||
|
public function __construct(string $importedAlias, IdentifierTypeNode $importedFrom, ?string $importedAs)
|
||||||
|
{
|
||||||
|
$this->importedAlias = $importedAlias;
|
||||||
|
$this->importedFrom = $importedFrom;
|
||||||
|
$this->importedAs = $importedAs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return trim(
|
||||||
|
"{$this->importedAlias} from {$this->importedFrom}"
|
||||||
|
. ($this->importedAs !== null ? " as {$this->importedAs}" : '')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -194,6 +194,11 @@ class PhpDocParser
|
|||||||
$tagValue = $this->parseTypeAliasTagValue($tokens);
|
$tagValue = $this->parseTypeAliasTagValue($tokens);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '@phpstan-import-type':
|
||||||
|
case '@psalm-import-type':
|
||||||
|
$tagValue = $this->parseTypeAliasImportTagValue($tokens);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
|
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
|
||||||
break;
|
break;
|
||||||
@ -382,6 +387,32 @@ class PhpDocParser
|
|||||||
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
|
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function parseTypeAliasImportTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasImportTagValueNode
|
||||||
|
{
|
||||||
|
$importedAlias = $tokens->currentTokenValue();
|
||||||
|
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||||
|
|
||||||
|
if (!$tokens->tryConsumeTokenValue('from')) {
|
||||||
|
throw new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
|
$tokens->currentTokenValue(),
|
||||||
|
$tokens->currentTokenType(),
|
||||||
|
$tokens->currentTokenOffset(),
|
||||||
|
Lexer::TOKEN_IDENTIFIER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$importedFrom = $this->typeParser->parse($tokens);
|
||||||
|
assert($importedFrom instanceof IdentifierTypeNode);
|
||||||
|
|
||||||
|
$importedAs = null;
|
||||||
|
if ($tokens->tryConsumeTokenValue('as')) {
|
||||||
|
$importedAs = $tokens->currentTokenValue();
|
||||||
|
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, $importedFrom, $importedAs);
|
||||||
|
}
|
||||||
|
|
||||||
private function parseOptionalVariableName(TokenIterator $tokens): string
|
private function parseOptionalVariableName(TokenIterator $tokens): string
|
||||||
{
|
{
|
||||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
|
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\ReturnTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||||
@ -68,6 +69,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase
|
|||||||
* @dataProvider provideTemplateTagsData
|
* @dataProvider provideTemplateTagsData
|
||||||
* @dataProvider provideExtendsTagsData
|
* @dataProvider provideExtendsTagsData
|
||||||
* @dataProvider provideTypeAliasTagsData
|
* @dataProvider provideTypeAliasTagsData
|
||||||
|
* @dataProvider provideTypeAliasImportTagsData
|
||||||
* @dataProvider provideRealWorldExampleData
|
* @dataProvider provideRealWorldExampleData
|
||||||
* @dataProvider provideDescriptionWithOrWithoutHtml
|
* @dataProvider provideDescriptionWithOrWithoutHtml
|
||||||
* @param string $label
|
* @param string $label
|
||||||
@ -2904,7 +2906,7 @@ some text in the middle'
|
|||||||
'@phpstan-type',
|
'@phpstan-type',
|
||||||
new InvalidTagValueNode(
|
new InvalidTagValueNode(
|
||||||
'TypeAlias',
|
'TypeAlias',
|
||||||
new ParserException(
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
'*/',
|
'*/',
|
||||||
Lexer::TOKEN_CLOSE_PHPDOC,
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||||
28,
|
28,
|
||||||
@ -2923,7 +2925,7 @@ some text in the middle'
|
|||||||
'@phpstan-type',
|
'@phpstan-type',
|
||||||
new InvalidTagValueNode(
|
new InvalidTagValueNode(
|
||||||
'',
|
'',
|
||||||
new ParserException(
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
'*/',
|
'*/',
|
||||||
Lexer::TOKEN_CLOSE_PHPDOC,
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||||
18,
|
18,
|
||||||
@ -2935,6 +2937,96 @@ some text in the middle'
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function provideTypeAliasImportTagsData(): \Iterator
|
||||||
|
{
|
||||||
|
yield [
|
||||||
|
'OK',
|
||||||
|
'/** @phpstan-import-type TypeAlias from AnotherClass */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@phpstan-import-type',
|
||||||
|
new TypeAliasImportTagValueNode(
|
||||||
|
'TypeAlias',
|
||||||
|
new IdentifierTypeNode('AnotherClass'),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'OK with alias',
|
||||||
|
'/** @phpstan-import-type TypeAlias from AnotherClass as DifferentAlias */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@phpstan-import-type',
|
||||||
|
new TypeAliasImportTagValueNode(
|
||||||
|
'TypeAlias',
|
||||||
|
new IdentifierTypeNode('AnotherClass'),
|
||||||
|
'DifferentAlias'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'invalid missing from',
|
||||||
|
'/** @phpstan-import-type TypeAlias */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@phpstan-import-type',
|
||||||
|
new InvalidTagValueNode(
|
||||||
|
'TypeAlias',
|
||||||
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
|
'*/',
|
||||||
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||||
|
35,
|
||||||
|
Lexer::TOKEN_IDENTIFIER
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'invalid missing from with alias',
|
||||||
|
'/** @phpstan-import-type TypeAlias as DifferentAlias */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@phpstan-import-type',
|
||||||
|
new InvalidTagValueNode(
|
||||||
|
'TypeAlias as DifferentAlias',
|
||||||
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
|
'as',
|
||||||
|
Lexer::TOKEN_IDENTIFIER,
|
||||||
|
35,
|
||||||
|
Lexer::TOKEN_IDENTIFIER
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'invalid empty',
|
||||||
|
'/** @phpstan-import-type */',
|
||||||
|
new PhpDocNode([
|
||||||
|
new PhpDocTagNode(
|
||||||
|
'@phpstan-import-type',
|
||||||
|
new InvalidTagValueNode(
|
||||||
|
'',
|
||||||
|
new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||||
|
'*/',
|
||||||
|
Lexer::TOKEN_CLOSE_PHPDOC,
|
||||||
|
25,
|
||||||
|
Lexer::TOKEN_IDENTIFIER
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function providerDebug(): \Iterator
|
public function providerDebug(): \Iterator
|
||||||
{
|
{
|
||||||
$sample = '/**
|
$sample = '/**
|
||||||
|
Loading…
Reference in New Issue
Block a user