Make requiring whitespace before description optional

This commit is contained in:
Richard van Velzen 2022-06-09 08:32:10 +02:00 committed by Ondřej Mirtes
parent 1e355a35e2
commit 3cb62d1084
2 changed files with 91 additions and 9 deletions

View File

@ -24,10 +24,14 @@ class PhpDocParser
/** @var ConstExprParser */
private $constantExprParser;
public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser)
/** @var bool */
private $requireWhitespaceBeforeDescription;
public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser, bool $requireWhitespaceBeforeDescription = false)
{
$this->typeParser = $typeParser;
$this->constantExprParser = $constantExprParser;
$this->requireWhitespaceBeforeDescription = $requireWhitespaceBeforeDescription;
}
@ -492,7 +496,8 @@ class PhpDocParser
}
if (
!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)
$this->requireWhitespaceBeforeDescription
&& !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)
&& !$tokens->isPrecededByHorizontalWhitespace()
) {
$tokens->consumeTokenType(Lexer::TOKEN_HORIZONTAL_WS); // will throw exception

View File

@ -53,12 +53,17 @@ class PhpDocParserTest extends TestCase
/** @var PhpDocParser */
private $phpDocParser;
/** @var PhpDocParser */
private $phpDocParserWithRequiredWhitespaceBeforeDescription;
protected function setUp(): void
{
parent::setUp();
$this->lexer = new Lexer();
$constExprParser = new ConstExprParser();
$this->phpDocParser = new PhpDocParser(new TypeParser($constExprParser), $constExprParser);
$typeParser = new TypeParser($constExprParser);
$this->phpDocParser = new PhpDocParser($typeParser, $constExprParser);
$this->phpDocParserWithRequiredWhitespaceBeforeDescription = new PhpDocParser($typeParser, $constExprParser, true);
}
@ -83,14 +88,37 @@ class PhpDocParserTest extends TestCase
* @dataProvider provideRealWorldExampleData
* @dataProvider provideDescriptionWithOrWithoutHtml
*/
public function testParse(string $label, string $input, PhpDocNode $expectedPhpDocNode, int $nextTokenType = Lexer::TOKEN_END): void
public function testParse(
string $label,
string $input,
PhpDocNode $expectedPhpDocNode,
?PhpDocNode $withRequiredWhitespaceBeforeDescriptionExpectedPhpDocNode = null
): void
{
$this->executeTestParse(
$this->phpDocParser,
$label,
$input,
$expectedPhpDocNode
);
$this->executeTestParse(
$this->phpDocParserWithRequiredWhitespaceBeforeDescription,
$label,
$input,
$withRequiredWhitespaceBeforeDescriptionExpectedPhpDocNode ?? $expectedPhpDocNode
);
}
private function executeTestParse(PhpDocParser $phpDocParser, string $label, string $input, PhpDocNode $expectedPhpDocNode): void
{
$tokens = new TokenIterator($this->lexer->tokenize($input));
$actualPhpDocNode = $this->phpDocParser->parse($tokens);
$actualPhpDocNode = $phpDocParser->parse($tokens);
$this->assertEquals($expectedPhpDocNode, $actualPhpDocNode, $label);
$this->assertSame((string) $expectedPhpDocNode, (string) $actualPhpDocNode);
$this->assertSame($nextTokenType, $tokens->currentTokenType());
$this->assertSame(Lexer::TOKEN_END, $tokens->currentTokenType());
}
@ -675,6 +703,16 @@ class PhpDocParserTest extends TestCase
)
),
]),
new PhpDocNode([
new PhpDocTagNode(
'@var',
new VarTagValueNode(
new IdentifierTypeNode('Foo'),
'$foo',
'#desc'
)
),
]),
];
yield [
@ -1459,6 +1497,15 @@ class PhpDocParserTest extends TestCase
yield [
'invalid variadic callable',
'/** @return \Closure(...int, string): string */',
new PhpDocNode([
new PhpDocTagNode(
'@return',
new ReturnTagValueNode(
new IdentifierTypeNode('\Closure'),
'(...int, string): string'
)
),
]),
new PhpDocNode([
new PhpDocTagNode(
'@return',
@ -2265,6 +2312,16 @@ class PhpDocParserTest extends TestCase
yield [
'callable with incomplete signature without return type',
'/** @var callable(int) */',
new PhpDocNode([
new PhpDocTagNode(
'@var',
new VarTagValueNode(
new IdentifierTypeNode('callable'),
'',
'(int)'
)
),
]),
new PhpDocNode([
new PhpDocTagNode(
'@var',
@ -4241,6 +4298,20 @@ Finder::findFiles('*.php')
'/**' . PHP_EOL .
' * @return Foo <strong>Important description' . PHP_EOL .
' */',
new PhpDocNode([
new PhpDocTagNode(
'@return',
new ReturnTagValueNode(
new GenericTypeNode(
new IdentifierTypeNode('Foo'),
[
new IdentifierTypeNode('strong'),
]
),
'Important description'
)
),
]),
new PhpDocNode([
new PhpDocTagNode(
'@return',
@ -4305,14 +4376,20 @@ Finder::findFiles('*.php')
* @dataProvider dataParseTagValue
* @param PhpDocNode $expectedPhpDocNode
*/
public function testParseTagValue(string $tag, string $phpDoc, Node $expectedPhpDocNode, int $nextTokenType = Lexer::TOKEN_END): void
public function testParseTagValue(string $tag, string $phpDoc, Node $expectedPhpDocNode): void
{
$this->executeTestParseTagValue($this->phpDocParser, $tag, $phpDoc, $expectedPhpDocNode);
$this->executeTestParseTagValue($this->phpDocParserWithRequiredWhitespaceBeforeDescription, $tag, $phpDoc, $expectedPhpDocNode);
}
private function executeTestParseTagValue(PhpDocParser $phpDocParser, string $tag, string $phpDoc, Node $expectedPhpDocNode): void
{
$tokens = new TokenIterator($this->lexer->tokenize($phpDoc));
$actualPhpDocNode = $this->phpDocParser->parseTagValue($tokens, $tag);
$actualPhpDocNode = $phpDocParser->parseTagValue($tokens, $tag);
$this->assertEquals($expectedPhpDocNode, $actualPhpDocNode);
$this->assertSame((string) $expectedPhpDocNode, (string) $actualPhpDocNode);
$this->assertSame($nextTokenType, $tokens->currentTokenType());
$this->assertSame(Lexer::TOKEN_END, $tokens->currentTokenType());
}
}