Skip to content

Commit b00d20a

Browse files
committed
add tests for comments on callable
1 parent e5bf7b5 commit b00d20a

File tree

3 files changed

+146
-4
lines changed

3 files changed

+146
-4
lines changed

src/Parser/TypeParser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNod
482482
$parameters[] = $this->parseCallableParameter($tokens);
483483
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
484484
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
485-
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
485+
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL, true);
486486
if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
487487
break;
488488
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\PhpDocParser\Printer;
4+
5+
use PHPStan\PhpDocParser\Ast\AbstractNodeVisitor;
6+
use PHPStan\PhpDocParser\Ast\Node;
7+
use PHPStan\PhpDocParser\Ast\NodeTraverser;
8+
use PHPStan\PhpDocParser\Ast\NodeVisitor;
9+
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
10+
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
11+
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
12+
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
13+
use PHPStan\PhpDocParser\Lexer\Lexer;
14+
use PHPStan\PhpDocParser\Parser\TokenIterator;
15+
use function array_unshift;
16+
17+
class PrintCallableWithSingleLineCommentTest extends PrinterTestBase
18+
{
19+
20+
/**
21+
* @return iterable<array{string, string}>
22+
*/
23+
public function dataAddCommentToParamsFront(): iterable
24+
{
25+
yield [
26+
self::nowdoc('
27+
/**
28+
* @param callable(Bar $bar): int $a
29+
*/'),
30+
self::nowdoc('
31+
/**
32+
* @param callable(// never pet a burning dog
33+
* Foo $foo,
34+
* Bar $bar): int $a
35+
*/'),
36+
];
37+
}
38+
39+
/**
40+
* @dataProvider dataAddCommentToParamsFront
41+
*/
42+
public function testAddCommentToParamsFront(string $phpDoc, string $expectedResult): void
43+
{
44+
$visitor = new class extends AbstractNodeVisitor {
45+
46+
public function enterNode(Node $node)
47+
{
48+
if ($node instanceof CallableTypeNode) {
49+
array_unshift($node->parameters, PrinterTestBase::withComment(
50+
new CallableTypeParameterNode(new IdentifierTypeNode('Foo'), false, false, '$foo', false),
51+
'// never pet a burning dog'
52+
));
53+
}
54+
55+
return $node;
56+
}
57+
58+
};
59+
60+
$lexer = new Lexer(true);
61+
$tokens = new TokenIterator($lexer->tokenize($phpDoc));
62+
$phpDocNode = $this->phpDocParser->parse($tokens);
63+
$cloningTraverser = new NodeTraverser([new NodeVisitor\CloningVisitor()]);
64+
$newNodes = $cloningTraverser->traverse([$phpDocNode]);
65+
66+
$changingTraverser = new NodeTraverser([$visitor]);
67+
68+
/** @var PhpDocNode $newNode */
69+
[$newNode] = $changingTraverser->traverse($newNodes);
70+
71+
$printer = new Printer();
72+
$actualResult = $printer->printFormatPreserving($newNode, $phpDocNode, $tokens);
73+
$this->assertSame($expectedResult, $actualResult);
74+
75+
$this->assertEquals(
76+
$this->unsetAttributes($newNode),
77+
$this->unsetAttributes($this->phpDocParser->parse(new TokenIterator($lexer->tokenize($actualResult))))
78+
);
79+
}
80+
81+
82+
/**
83+
* @return iterable<array{string, string}>
84+
*/
85+
public function dataPrintArrayFormatPreservingAddMiddle(): iterable
86+
{
87+
yield [
88+
self::nowdoc('
89+
/**
90+
* @param callable(Foo $foo): int $a
91+
*/'),
92+
self::nowdoc('
93+
/**
94+
* @param callable(Foo $foo,
95+
* // never pet a burning dog
96+
* Bar $bar): int $a
97+
*/'),
98+
];
99+
}
100+
101+
/**
102+
* @dataProvider dataPrintArrayFormatPreservingAddMiddle
103+
*/
104+
public function testPrintFormatPreservingSingleLineAddMiddle(string $phpDoc, string $expectedResult): void
105+
{
106+
$visitor = new class extends AbstractNodeVisitor {
107+
108+
public function enterNode(Node $node)
109+
{
110+
if ($node instanceof CallableTypeNode) {
111+
$node->parameters[] = PrinterTestBase::withComment(
112+
new CallableTypeParameterNode(new IdentifierTypeNode('Bar'), false, false, '$bar', false),
113+
'// never pet a burning dog'
114+
);
115+
}
116+
117+
return $node;
118+
}
119+
120+
};
121+
122+
$lexer = new Lexer(true);
123+
$tokens = new TokenIterator($lexer->tokenize($phpDoc));
124+
$phpDocNode = $this->phpDocParser->parse($tokens);
125+
$cloningTraverser = new NodeTraverser([new NodeVisitor\CloningVisitor()]);
126+
$newNodes = $cloningTraverser->traverse([$phpDocNode]);
127+
128+
$changingTraverser = new NodeTraverser([$visitor]);
129+
130+
/** @var PhpDocNode $newNode */
131+
[$newNode] = $changingTraverser->traverse($newNodes);
132+
133+
$printer = new Printer();
134+
$actualResult = $printer->printFormatPreserving($newNode, $phpDocNode, $tokens);
135+
$this->assertSame($expectedResult, $actualResult);
136+
137+
$this->assertEquals(
138+
$this->unsetAttributes($newNode),
139+
$this->unsetAttributes($this->phpDocParser->parse(new TokenIterator($lexer->tokenize($actualResult))))
140+
);
141+
}
142+
143+
}

tests/PHPStan/Printer/PrinterTestBase.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use PHPStan\PhpDocParser\Ast\Node;
99
use PHPStan\PhpDocParser\Ast\NodeTraverser;
1010
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
11-
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
1211
use PHPStan\PhpDocParser\Parser\ConstExprParser;
1312
use PHPStan\PhpDocParser\Parser\PhpDocParser;
1413
use PHPStan\PhpDocParser\Parser\TypeParser;
@@ -34,11 +33,11 @@ abstract class PrinterTestBase extends TestCase
3433
protected $phpDocParser;
3534

3635
/**
37-
* @template TNode of TypeNode
36+
* @template TNode of Node
3837
* @param TNode $node
3938
* @return TNode
4039
*/
41-
public static function withComment(TypeNode $node, string $comment): TypeNode
40+
public static function withComment(Node $node, string $comment): Node
4241
{
4342
$node->setAttribute(Attribute::COMMENTS, [new Comment($comment)]);
4443
return $node;

0 commit comments

Comments
 (0)