@@ -78,10 +78,44 @@ public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode
78
78
79
79
$ children = [];
80
80
81
- if (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
82
- $ children [] = $ this ->parseChild ($ tokens );
83
- while ($ tokens ->tryConsumeTokenType (Lexer::TOKEN_PHPDOC_EOL ) && !$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
81
+ if ($ this ->parseDoctrineAnnotations ) {
82
+ if (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
83
+ $ lastChild = $ this ->parseChild ($ tokens );
84
+ $ children [] = $ lastChild ;
85
+ while (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
86
+ if (
87
+ $ lastChild instanceof Ast \PhpDoc \PhpDocTagNode
88
+ && (
89
+ $ lastChild ->value instanceof Doctrine \DoctrineTagValueNode
90
+ || $ lastChild ->value instanceof Ast \PhpDoc \GenericTagValueNode
91
+ )
92
+ ) {
93
+ $ tokens ->tryConsumeTokenType (Lexer::TOKEN_PHPDOC_EOL );
94
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
95
+ break ;
96
+ }
97
+ $ lastChild = $ this ->parseChild ($ tokens );
98
+ $ children [] = $ lastChild ;
99
+ continue ;
100
+ }
101
+
102
+ if (!$ tokens ->tryConsumeTokenType (Lexer::TOKEN_PHPDOC_EOL )) {
103
+ break ;
104
+ }
105
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
106
+ break ;
107
+ }
108
+
109
+ $ lastChild = $ this ->parseChild ($ tokens );
110
+ $ children [] = $ lastChild ;
111
+ }
112
+ }
113
+ } else {
114
+ if (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
84
115
$ children [] = $ this ->parseChild ($ tokens );
116
+ while ($ tokens ->tryConsumeTokenType (Lexer::TOKEN_PHPDOC_EOL ) && !$ tokens ->isCurrentTokenType (Lexer::TOKEN_CLOSE_PHPDOC )) {
117
+ $ children [] = $ this ->parseChild ($ tokens );
118
+ }
85
119
}
86
120
}
87
121
@@ -119,6 +153,7 @@ public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode
119
153
}
120
154
121
155
156
+ /** @phpstan-impure */
122
157
private function parseChild (TokenIterator $ tokens ): Ast \PhpDoc \PhpDocChildNode
123
158
{
124
159
if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_PHPDOC_TAG )) {
@@ -202,6 +237,63 @@ private function parseText(TokenIterator $tokens): Ast\PhpDoc\PhpDocTextNode
202
237
}
203
238
204
239
240
+ private function parseOptionalDescriptionAfterDoctrineTag (TokenIterator $ tokens ): string
241
+ {
242
+ $ text = '' ;
243
+
244
+ while (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_PHPDOC_EOL )) {
245
+ $ text .= $ tokens ->getSkippedHorizontalWhiteSpaceIfAny () . $ tokens ->joinUntil (Lexer::TOKEN_PHPDOC_TAG , Lexer::TOKEN_DOCTRINE_TAG , Lexer::TOKEN_PHPDOC_EOL , Lexer::TOKEN_CLOSE_PHPDOC , Lexer::TOKEN_END );
246
+
247
+ if (!$ tokens ->isCurrentTokenType (Lexer::TOKEN_PHPDOC_EOL )) {
248
+ if (!$ tokens ->isPrecededByHorizontalWhitespace ()) {
249
+ return trim ($ text . $ this ->parseText ($ tokens )->text , " \t" );
250
+ }
251
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_PHPDOC_TAG )) {
252
+ $ tokens ->pushSavePoint ();
253
+ $ child = $ this ->parseChild ($ tokens );
254
+ if ($ child instanceof Ast \PhpDoc \PhpDocTagNode) {
255
+ if (
256
+ $ child ->value instanceof Ast \PhpDoc \GenericTagValueNode
257
+ || $ child ->value instanceof Doctrine \DoctrineTagValueNode
258
+ ) {
259
+ $ tokens ->rollback ();
260
+ break ;
261
+ }
262
+ if ($ child ->value instanceof Ast \PhpDoc \InvalidTagValueNode) {
263
+ $ tokens ->rollback ();
264
+ $ tokens ->pushSavePoint ();
265
+ $ tokens ->next ();
266
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_OPEN_PARENTHESES )) {
267
+ $ tokens ->rollback ();
268
+ break ;
269
+ }
270
+ $ tokens ->rollback ();
271
+ return trim ($ text . $ this ->parseText ($ tokens )->text , " \t" );
272
+ }
273
+ }
274
+
275
+ $ tokens ->rollback ();
276
+ return trim ($ text . $ this ->parseText ($ tokens )->text , " \t" );
277
+ }
278
+ break ;
279
+ }
280
+
281
+ $ tokens ->pushSavePoint ();
282
+ $ tokens ->next ();
283
+
284
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_PHPDOC_TAG , Lexer::TOKEN_DOCTRINE_TAG , Lexer::TOKEN_PHPDOC_EOL , Lexer::TOKEN_CLOSE_PHPDOC , Lexer::TOKEN_END )) {
285
+ $ tokens ->rollback ();
286
+ break ;
287
+ }
288
+
289
+ $ tokens ->dropSavePoint ();
290
+ $ text .= "\n" ;
291
+ }
292
+
293
+ return trim ($ text , " \t" );
294
+ }
295
+
296
+
205
297
public function parseTag (TokenIterator $ tokens ): Ast \PhpDoc \PhpDocTagNode
206
298
{
207
299
$ tag = $ tokens ->currentTokenValue ();
@@ -333,15 +425,17 @@ public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\Ph
333
425
break ;
334
426
335
427
default :
336
- if (
337
- $ this ->parseDoctrineAnnotations
338
- && $ tokens ->isCurrentTokenType (Lexer::TOKEN_OPEN_PARENTHESES )
339
- ) {
340
- $ tagValue = $ this ->parseDoctrineTagValue ($ tokens , $ tag );
428
+ if ($ this ->parseDoctrineAnnotations ) {
429
+ if ($ tokens ->isCurrentTokenType (Lexer::TOKEN_OPEN_PARENTHESES )) {
430
+ $ tagValue = $ this ->parseDoctrineTagValue ($ tokens , $ tag );
431
+ } else {
432
+ $ tagValue = new Ast \PhpDoc \GenericTagValueNode ($ this ->parseOptionalDescriptionAfterDoctrineTag ($ tokens ));
433
+ }
341
434
break ;
342
435
}
343
436
344
437
$ tagValue = new Ast \PhpDoc \GenericTagValueNode ($ this ->parseOptionalDescription ($ tokens ));
438
+
345
439
break ;
346
440
}
347
441
@@ -368,7 +462,7 @@ private function parseDoctrineTagValue(TokenIterator $tokens, string $tag): Ast\
368
462
$ startLine ,
369
463
$ startIndex
370
464
),
371
- $ this ->parseOptionalDescription ($ tokens )
465
+ $ this ->parseOptionalDescriptionAfterDoctrineTag ($ tokens )
372
466
);
373
467
}
374
468
0 commit comments