diff --git a/src/Ast/PhpDoc/TemplateTagValueNode.php b/src/Ast/PhpDoc/TemplateTagValueNode.php index 1595956b..1d3c70e4 100644 --- a/src/Ast/PhpDoc/TemplateTagValueNode.php +++ b/src/Ast/PhpDoc/TemplateTagValueNode.php @@ -17,13 +17,17 @@ class TemplateTagValueNode implements PhpDocTagValueNode /** @var TypeNode|null */ public $bound; + /** @var TypeNode|null */ + public $default; + /** @var string (may be empty) */ public $description; - public function __construct(string $name, ?TypeNode $bound, string $description) + public function __construct(string $name, ?TypeNode $bound, string $description, ?TypeNode $default = null) { $this->name = $name; $this->bound = $bound; + $this->default = $default; $this->description = $description; } @@ -31,7 +35,8 @@ public function __construct(string $name, ?TypeNode $bound, string $description) public function __toString(): string { $bound = $this->bound !== null ? " of {$this->bound}" : ''; - return trim("{$this->name}{$bound} {$this->description}"); + $default = $this->default !== null ? " = {$this->default}" : ''; + return trim("{$this->name}{$bound}{$default} {$this->description}"); } } diff --git a/src/Parser/PhpDocParser.php b/src/Parser/PhpDocParser.php index cca8e9bd..2b6b796d 100644 --- a/src/Parser/PhpDocParser.php +++ b/src/Parser/PhpDocParser.php @@ -402,9 +402,15 @@ private function parseTemplateTagValue(TokenIterator $tokens): Ast\PhpDoc\Templa $bound = null; } + if ($tokens->tryConsumeTokenValue('=')) { + $default = $this->typeParser->parse($tokens); + } else { + $default = null; + } + $description = $this->parseOptionalDescription($tokens); - return new Ast\PhpDoc\TemplateTagValueNode($name, $bound, $description); + return new Ast\PhpDoc\TemplateTagValueNode($name, $bound, $description, $default); } private function parseExtendsTagValue(string $tagName, TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode diff --git a/tests/PHPStan/Parser/PhpDocParserTest.php b/tests/PHPStan/Parser/PhpDocParserTest.php index 791e995c..69186a4b 100644 --- a/tests/PHPStan/Parser/PhpDocParserTest.php +++ b/tests/PHPStan/Parser/PhpDocParserTest.php @@ -3345,6 +3345,54 @@ public function provideTemplateTagsData(): Iterator ), ]), ]; + + yield [ + 'OK with default', + '/** @template T = string */', + new PhpDocNode([ + new PhpDocTagNode( + '@template', + new TemplateTagValueNode( + 'T', + null, + '', + new IdentifierTypeNode('string') + ) + ), + ]), + ]; + + yield [ + 'OK with default and description', + '/** @template T = string the value type */', + new PhpDocNode([ + new PhpDocTagNode( + '@template', + new TemplateTagValueNode( + 'T', + null, + 'the value type', + new IdentifierTypeNode('string') + ) + ), + ]), + ]; + + yield [ + 'OK with bound and default and description', + '/** @template T of string = \'\' the value type */', + new PhpDocNode([ + new PhpDocTagNode( + '@template', + new TemplateTagValueNode( + 'T', + new IdentifierTypeNode('string'), + 'the value type', + new ConstTypeNode(new ConstExprStringNode('')) + ) + ), + ]), + ]; } public function provideExtendsTagsData(): Iterator