From 4e272700b356cac9050a2068caf4c12232ccb442 Mon Sep 17 00:00:00 2001 From: Jan Tvrdik Date: Sun, 19 Nov 2017 18:07:18 +0100 Subject: [PATCH] PhpDocParser: support variadic parameters in @param tag --- doc/grammars/phpdoc-param.peg | 5 ++++- src/Ast/PhpDoc/ParamTagValueNode.php | 9 +++++++-- src/Parser/PhpDocParser.php | 3 ++- tests/PHPStan/Parser/PhpDocParserTest.php | 21 +++++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/doc/grammars/phpdoc-param.peg b/doc/grammars/phpdoc-param.peg index dd1e284..5a5c1b3 100644 --- a/doc/grammars/phpdoc-param.peg +++ b/doc/grammars/phpdoc-param.peg @@ -1,9 +1,12 @@ PhpDocParam - = AnnotationName Type ParameterName Description? + = AnnotationName Type IsVariadic? ParameterName Description? AnnotationName = '@param' +IsVariaric + = '...' + ParameterName = '$' [a-zA-Z_\127-\255][a-zA-Z0-9_\127-\255]* diff --git a/src/Ast/PhpDoc/ParamTagValueNode.php b/src/Ast/PhpDoc/ParamTagValueNode.php index eebf34a..c11cc85 100644 --- a/src/Ast/PhpDoc/ParamTagValueNode.php +++ b/src/Ast/PhpDoc/ParamTagValueNode.php @@ -10,15 +10,19 @@ class ParamTagValueNode implements PhpDocTagValueNode /** @var TypeNode */ public $type; + /** @var bool */ + public $isVariadic; + /** @var string (may be empty) */ public $parameterName; /** @var string (may be empty) */ public $description; - public function __construct(TypeNode $type, string $parameterName, string $description) + public function __construct(TypeNode $type, bool $isVariadic, string $parameterName, string $description) { $this->type = $type; + $this->isVariadic = $isVariadic; $this->parameterName = $parameterName; $this->description = $description; } @@ -26,7 +30,8 @@ class ParamTagValueNode implements PhpDocTagValueNode public function __toString(): string { - return trim("{$this->type} {$this->parameterName} {$this->description}"); + $variadic = $this->isVariadic ? '...' : ''; + return trim("{$this->type} {$variadic}{$this->parameterName} {$this->description}"); } } diff --git a/src/Parser/PhpDocParser.php b/src/Parser/PhpDocParser.php index 9c5b8ac..d807e0f 100644 --- a/src/Parser/PhpDocParser.php +++ b/src/Parser/PhpDocParser.php @@ -122,9 +122,10 @@ class PhpDocParser private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamTagValueNode { $type = $this->typeParser->parse($tokens); + $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens); - return new Ast\PhpDoc\ParamTagValueNode($type, $parameterName, $description); + return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description); } diff --git a/tests/PHPStan/Parser/PhpDocParserTest.php b/tests/PHPStan/Parser/PhpDocParserTest.php index a403936..1b37d9c 100644 --- a/tests/PHPStan/Parser/PhpDocParserTest.php +++ b/tests/PHPStan/Parser/PhpDocParserTest.php @@ -95,6 +95,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Foo'), + false, '$foo', '' ) @@ -127,6 +128,22 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Foo'), + false, + '$foo', + 'optional description ' + ) + ), + ]), + ], + [ + '/** @param Foo ...$foo optional description */', + new PhpDocNode([ + new PhpDocTextNode(' '), + new PhpDocTagNode( + '@param', + new ParamTagValueNode( + new IdentifierTypeNode('Foo'), + true, '$foo', 'optional description ' ) @@ -289,6 +306,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Foo'), + false, '$foo', '1st multi world description' ) @@ -298,6 +316,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Bar'), + false, '$bar', '2nd multi world description' ) @@ -317,6 +336,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Foo'), + false, '$foo', '1st multi world description' ) @@ -326,6 +346,7 @@ class PhpDocParserTest extends \PHPUnit\Framework\TestCase '@param', new ParamTagValueNode( new IdentifierTypeNode('Bar'), + false, '$bar', '2nd multi world description' )