Support for parsing @mixin Type [description]

This commit is contained in:
Ondrej Mirtes 2020-05-02 08:25:41 +02:00
parent fde6cca6d9
commit 956e7215c7
No known key found for this signature in database
GPG Key ID: 8E730BA25823D8B5
4 changed files with 154 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<?php declare(strict_types = 1);
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
class MixinTagValueNode implements PhpDocTagValueNode
{
/** @var TypeNode */
public $type;
/** @var string (may be empty) */
public $description;
public function __construct(TypeNode $type, string $description)
{
$this->type = $type;
$this->description = $description;
}
public function __toString(): string
{
return trim("{$this->type} {$this->description}");
}
}

View File

@ -154,6 +154,20 @@ class PhpDocNode implements Node
}
/**
* @return MixinTagValueNode[]
*/
public function getMixinTagValues(string $tagName = '@mixin'): array
{
return array_column(
array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag): bool {
return $tag->value instanceof MixinTagValueNode;
}),
'value'
);
}
/**
* @return \PHPStan\PhpDocParser\Ast\PhpDoc\DeprecatedTagValueNode[]
*/

View File

@ -136,6 +136,10 @@ class PhpDocParser
$tagValue = $this->parseThrowsTagValue($tokens);
break;
case '@mixin':
$tagValue = $this->parseMixinTagValue($tokens);
break;
case '@deprecated':
$tagValue = $this->parseDeprecatedTagValue($tokens);
break;
@ -235,6 +239,13 @@ class PhpDocParser
return new Ast\PhpDoc\ThrowsTagValueNode($type, $description);
}
private function parseMixinTagValue(TokenIterator $tokens): Ast\PhpDoc\MixinTagValueNode
{
$type = $this->typeParser->parse($tokens);
$description = $this->parseOptionalDescription($tokens, true);
return new Ast\PhpDoc\MixinTagValueNode($type, $description);
}
private function parseDeprecatedTagValue(TokenIterator $tokens): Ast\PhpDoc\DeprecatedTagValueNode
{
$description = $this->parseOptionalDescription($tokens);

View File

@ -12,6 +12,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
@ -54,6 +55,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase
* @dataProvider provideVarTagsData
* @dataProvider provideReturnTagsData
* @dataProvider provideThrowsTagsData
* @dataProvider provideMixinTagsData
* @dataProvider provideDeprecatedTagsData
* @dataProvider providePropertyTagsData
* @dataProvider provideMethodTagsData
@ -1064,6 +1066,105 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase
];
}
public function provideMixinTagsData(): \Iterator
{
yield [
'OK without description',
'/** @mixin Foo */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new MixinTagValueNode(
new IdentifierTypeNode('Foo'),
''
)
),
]),
];
yield [
'OK with description',
'/** @mixin Foo optional description */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new MixinTagValueNode(
new IdentifierTypeNode('Foo'),
'optional description'
)
),
]),
];
yield [
'OK with description that starts with TOKEN_OPEN_SQUARE_BRACKET',
'/** @mixin Foo [Bar] */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new MixinTagValueNode(
new IdentifierTypeNode('Foo'),
'[Bar]'
)
),
]),
];
yield [
'invalid without type and description',
'/** @mixin */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new InvalidTagValueNode(
'',
new \PHPStan\PhpDocParser\Parser\ParserException(
'*/',
Lexer::TOKEN_CLOSE_PHPDOC,
11,
Lexer::TOKEN_IDENTIFIER
)
)
),
]),
];
yield [
'invalid with type and disallowed description start token',
'/** @mixin Foo | #desc */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new InvalidTagValueNode(
'Foo | #desc',
new \PHPStan\PhpDocParser\Parser\ParserException(
'#desc',
Lexer::TOKEN_OTHER,
17,
Lexer::TOKEN_IDENTIFIER
)
)
),
]),
];
yield [
'generic @mixin',
'/** @mixin Foo<Bar> */',
new PhpDocNode([
new PhpDocTagNode(
'@mixin',
new MixinTagValueNode(
new GenericTypeNode(new IdentifierTypeNode('Foo'), [
new IdentifierTypeNode('Bar'),
]),
''
)
),
]),
];
}
public function provideDeprecatedTagsData(): \Iterator
{
yield [