Skip to content

Commit bfa36e1

Browse files
committed
comments as attributes
1 parent 21883d2 commit bfa36e1

File tree

8 files changed

+139
-135
lines changed

8 files changed

+139
-135
lines changed

src/Ast/Attribute.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ final class Attribute
1313

1414
public const ORIGINAL_NODE = 'originalNode';
1515

16+
public const COMMENT = 'comment';
17+
1618
}

src/Ast/Type/ArrayShapeNode.php

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
namespace PHPStan\PhpDocParser\Ast\Type;
44

55
use PHPStan\PhpDocParser\Ast\NodeAttributes;
6-
use function array_filter;
7-
use function count;
6+
use function implode;
87

98
class ArrayShapeNode implements TypeNode
109
{
@@ -14,7 +13,7 @@ class ArrayShapeNode implements TypeNode
1413

1514
use NodeAttributes;
1615

17-
/** @var array<ArrayShapeItemNode|CommentNode|IdentifierTypeNode> */
16+
/** @var ArrayShapeItemNode[] */
1817
public $items;
1918

2019
/** @var bool */
@@ -24,7 +23,7 @@ class ArrayShapeNode implements TypeNode
2423
public $kind;
2524

2625
/**
27-
* @param array<ArrayShapeItemNode|CommentNode|IdentifierTypeNode> $items
26+
* @param ArrayShapeItemNode[] $items
2827
* @param self::KIND_* $kind
2928
*/
3029
public function __construct(array $items, bool $sealed = true, string $kind = self::KIND_ARRAY)
@@ -34,15 +33,6 @@ public function __construct(array $items, bool $sealed = true, string $kind = se
3433
$this->kind = $kind;
3534
}
3635

37-
/**
38-
* @return array<ArrayShapeItemNode>
39-
*/
40-
public function items(): array
41-
{
42-
return array_filter($this->items, static function ($item) {
43-
return $item instanceof ArrayShapeItemNode;
44-
});
45-
}
4636

4737
public function __toString(): string
4838
{
@@ -52,18 +42,7 @@ public function __toString(): string
5242
$items[] = '...';
5343
}
5444

55-
$res = $this->kind . '{';
56-
foreach ($items as $idx => $item) {
57-
$res .= $item;
58-
59-
if (!($item instanceof ArrayShapeItemNode) || $idx >= count($items) - 1) {
60-
continue;
61-
}
62-
63-
$res .= ', ';
64-
65-
}
66-
return $res . '}';
45+
return $this->kind . '{' . implode(', ', $items) . '}';
6746
}
6847

6948
}

src/Ast/Type/CommentNode.php

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/Lexer/Lexer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ private function generateRegexp(): string
163163
self::TOKEN_CLOSE_CURLY_BRACKET => '\\}',
164164

165165
self::TOKEN_COMMA => ',',
166-
self::TOKEN_COMMENT => '//',
166+
self::TOKEN_COMMENT => '(\/\/[^\n]*|\/\*(?!\*)[^*]*\*+([^\/][^*]*\*+)*\/)',
167167
self::TOKEN_VARIADIC => '\\.\\.\\.',
168168
self::TOKEN_DOUBLE_COLON => '::',
169169
self::TOKEN_DOUBLE_ARROW => '=>',

src/Parser/TokenIterator.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class TokenIterator
2424
private $savePoints = [];
2525

2626
/** @var list<int> */
27-
private $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS];
27+
private $skippedTokenTypes = [
28+
Lexer::TOKEN_HORIZONTAL_WS,
29+
];
2830

2931
/** @var string|null */
3032
private $newline = null;
@@ -303,6 +305,10 @@ public function rollback(): void
303305
$this->index = $index;
304306
}
305307

308+
// public function popCurrentToken(): array {
309+
// $this->tokens = array_splice($this->)
310+
// }
311+
306312

307313
/**
308314
* @throws ParserException

src/Parser/TypeParser.php

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@ class TypeParser
2222
/** @var bool */
2323
private $useLinesAttributes;
2424

25+
/** @var bool */
26+
private $useCommentsAttributes;
27+
2528
/** @var bool */
2629
private $useIndexAttributes;
2730

2831
/**
29-
* @param array{lines?: bool, indexes?: bool} $usedAttributes
32+
* @param array{
33+
* lines?: bool,
34+
* indexes?: bool,
35+
* comments?: bool
36+
* } $usedAttributes
3037
*/
3138
public function __construct(
3239
?ConstExprParser $constExprParser = null,
@@ -38,6 +45,7 @@ public function __construct(
3845
$this->quoteAwareConstExprString = $quoteAwareConstExprString;
3946
$this->useLinesAttributes = $usedAttributes['lines'] ?? false;
4047
$this->useIndexAttributes = $usedAttributes['indexes'] ?? false;
48+
$this->useCommentsAttributes = $usedAttributes['comments'] ?? false;
4149
}
4250

4351
/** @phpstan-impure */
@@ -66,15 +74,29 @@ public function parse(TokenIterator $tokens): Ast\Type\TypeNode
6674
* @internal
6775
* @template T of Ast\Node
6876
* @param T $type
77+
* @param list<Ast\Comment> $comments
6978
* @return T
7079
*/
71-
public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex): Ast\Node
80+
public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex, array $comments = []): Ast\Node
7281
{
82+
if($tokens->currentTokenType() == Lexer::TOKEN_COMMENT) {
83+
$comments[] = new Ast\Comment(
84+
$tokens->currentTokenValue(),
85+
$tokens->currentTokenLine(),
86+
$tokens->currentTokenIndex()
87+
);
88+
$tokens->next();
89+
}
90+
7391
if ($this->useLinesAttributes) {
7492
$type->setAttribute(Ast\Attribute::START_LINE, $startLine);
7593
$type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
7694
}
7795

96+
if ($this->useCommentsAttributes) {
97+
$type->setAttribute(Ast\Attribute::COMMENT, $comments);
98+
}
99+
78100
if ($this->useIndexAttributes) {
79101
$type->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
80102
$type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
@@ -136,6 +158,7 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
136158
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
137159
}
138160

161+
139162
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
140163
$type = $this->enrichWithAttributes($tokens, new Ast\Type\ThisTypeNode(), $startLine, $startIndex);
141164

@@ -748,28 +771,24 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type,
748771
$items = [];
749772
$sealed = true;
750773

774+
$comments = [];
775+
751776
do {
752-
$tokens->pushSavePoint();
753-
$tokens->next();
754-
$tab = "\t";
755-
if ($tokens->currentTokenType() === Lexer::TOKEN_CLOSE_CURLY_BRACKET) {
756-
$tab = '';
757-
}
758-
$tokens->rollback();
759-
if ($tokens->currentTokenType() === Lexer::TOKEN_PHPDOC_EOL) {
760-
$startLine = $tokens->currentTokenLine();
761-
$startIndex = $tokens->currentTokenIndex();
762-
$items[] = $this->enrichWithAttributes(
763-
$tokens,
764-
new Ast\Type\IdentifierTypeNode("\n$tab"),
765-
$startLine,
766-
$startIndex
767-
);
768-
$tokens->next();
769-
}
777+
while(1) {
778+
if($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)){
779+
continue;
780+
}
781+
else if($tokens->currentTokenType() == Lexer::TOKEN_COMMENT) {
782+
$comments[] = new Ast\Comment($tokens->currentTokenValue(), $tokens->currentTokenLine(), $tokens->currentTokenIndex());
783+
$tokens->next();
784+
}
785+
else {
786+
break;
787+
}
788+
};
770789

771790
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
772-
return new Ast\Type\ArrayShapeNode($items, true, $kind);
791+
return new Ast\Type\ArrayShapeNode($items, true, $kind);
773792
}
774793

775794
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC)) {
@@ -778,23 +797,15 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type,
778797
break;
779798
}
780799

781-
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMENT)) {
782-
$items[] = $this->parseSimpleComment($tokens);
783-
}
784-
785-
if ($tokens->currentTokenType() === Lexer::TOKEN_PHPDOC_EOL) {
786-
$startLine = $tokens->currentTokenLine();
787-
$startIndex = $tokens->currentTokenIndex();
788-
$items[] = $this->enrichWithAttributes(
789-
$tokens,
790-
new Ast\Type\IdentifierTypeNode("\n\t"),
791-
$startLine,
792-
$startIndex
793-
);
794-
$tokens->next();
795-
}
796-
797-
$items[] = $this->parseArrayShapeItem($tokens);
800+
$startIndex = $tokens->currentTokenIndex();
801+
$startLine = $tokens->currentTokenLine();
802+
$items[] = $this->enrichWithAttributes(
803+
$tokens,
804+
$this->parseArrayShapeItem($tokens),
805+
$startLine,
806+
$startIndex,
807+
$comments
808+
);
798809

799810
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
800811
} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
@@ -805,25 +816,6 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type,
805816
return new Ast\Type\ArrayShapeNode($items, $sealed, $kind);
806817
}
807818

808-
private function parseSimpleComment(TokenIterator $tokens): Ast\Type\CommentNode
809-
{
810-
$startLine = $tokens->currentTokenLine();
811-
$startIndex = $tokens->currentTokenIndex();
812-
813-
$text = '';
814-
815-
while ($tokens->currentTokenType() !== Lexer::TOKEN_PHPDOC_EOL) {
816-
$text .= $tokens->currentTokenValue();
817-
$tokens->next(false);
818-
}
819-
820-
return $this->enrichWithAttributes(
821-
$tokens,
822-
new Ast\Type\CommentNode($text),
823-
$startLine,
824-
$startIndex
825-
);
826-
}
827819

828820
/** @phpstan-impure */
829821
private function parseArrayShapeItem(TokenIterator $tokens): Ast\Type\ArrayShapeItemNode

src/Printer/Printer.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,15 @@ private function printTagValue(PhpDocTagValueNode $node): string
339339
private function printType(TypeNode $node): string
340340
{
341341
if ($node instanceof ArrayShapeNode) {
342-
return (string) $node;
342+
$items = array_map(function (ArrayShapeItemNode $item): string {
343+
return $this->printType($item);
344+
}, $node->items);
345+
346+
if (! $node->sealed) {
347+
$items[] = '...';
348+
}
349+
350+
return $node->kind . '{' . implode(', ', $items) . '}';
343351
}
344352
if ($node instanceof ArrayShapeItemNode) {
345353
if ($node->keyName !== null) {

0 commit comments

Comments
 (0)