@@ -406,7 +406,7 @@ namespace ts {
406
406
visitNode ( cbNode , ( < JSDocTypedefTag > node ) . name ) ||
407
407
visitNode ( cbNode , ( < JSDocTypedefTag > node ) . type ) ;
408
408
case SyntaxKind . JSDocTypeLiteral :
409
- return visitNodes ( cbNodes , ( < JSDocTypeLiteral > node ) . members ) ;
409
+ return visitNodes ( cbNodes , ( < JSDocTypeLiteral > node ) . jsDocPropertyTags ) ;
410
410
case SyntaxKind . JSDocPropertyTag :
411
411
return visitNode ( cbNode , ( < JSDocPropertyTag > node ) . typeExpression ) ||
412
412
visitNode ( cbNode , ( < JSDocPropertyTag > node ) . name ) ;
@@ -4113,9 +4113,9 @@ namespace ts {
4113
4113
const isAsync = ! ! ( node . flags & NodeFlags . Async ) ;
4114
4114
node . name =
4115
4115
isGenerator && isAsync ? doInYieldAndAwaitContext ( parseOptionalIdentifier ) :
4116
- isGenerator ? doInYieldContext ( parseOptionalIdentifier ) :
4117
- isAsync ? doInAwaitContext ( parseOptionalIdentifier ) :
4118
- parseOptionalIdentifier ( ) ;
4116
+ isGenerator ? doInYieldContext ( parseOptionalIdentifier ) :
4117
+ isAsync ? doInAwaitContext ( parseOptionalIdentifier ) :
4118
+ parseOptionalIdentifier ( ) ;
4119
4119
4120
4120
fillSignature ( SyntaxKind . ColonToken , /*yieldContext*/ isGenerator , /*awaitContext*/ isAsync , /*requireCompleteParameterList*/ false , node ) ;
4121
4121
node . body = parseFunctionBlock ( /*allowYield*/ isGenerator , /*allowAwait*/ isAsync , /*ignoreMissingOpenBrace*/ false ) ;
@@ -6066,9 +6066,6 @@ namespace ts {
6066
6066
Debug . assert ( end <= content . length ) ;
6067
6067
6068
6068
let tags : NodeArray < JSDocTag > ;
6069
- let currentParentJSDocTag : JSDocParentTag ;
6070
- let currentParentJSDocTagEnd : number ;
6071
-
6072
6069
let result : JSDocComment ;
6073
6070
6074
6071
// Check for /** (JSDoc opening part)
@@ -6125,10 +6122,6 @@ namespace ts {
6125
6122
nextJSDocToken ( ) ;
6126
6123
}
6127
6124
6128
- if ( currentParentJSDocTag ) {
6129
- finishCurrentParentTag ( ) ;
6130
- }
6131
-
6132
6125
result = createJSDocComment ( ) ;
6133
6126
6134
6127
} ) ;
@@ -6152,40 +6145,6 @@ namespace ts {
6152
6145
}
6153
6146
}
6154
6147
6155
- function finishCurrentParentTag ( ) : void {
6156
- if ( ! currentParentJSDocTag ) {
6157
- return ;
6158
- }
6159
-
6160
- if ( currentParentJSDocTag . kind === SyntaxKind . JSDocTypedefTag ) {
6161
- const typedefTag = < JSDocTypedefTag > currentParentJSDocTag ;
6162
- if ( typedefTag . jsDocTypeTag ) {
6163
- if ( typedefTag . jsDocTypeTag . typeExpression . type . kind === SyntaxKind . JSDocTypeReference ) {
6164
- const typeTagtype = < JSDocTypeReference > typedefTag . jsDocTypeTag . typeExpression . type ;
6165
- if ( ( typeTagtype . name . kind !== SyntaxKind . Identifier ) ||
6166
- ( < Identifier > typeTagtype . name ) . text !== "Object" ) {
6167
- typedefTag . type = typedefTag . jsDocTypeTag . typeExpression . type ;
6168
- }
6169
- }
6170
- else {
6171
- typedefTag . type = typedefTag . jsDocTypeTag . typeExpression . type ;
6172
- }
6173
- }
6174
- if ( ! typedefTag . type && typedefTag . jsDocPropertyTags && typedefTag . jsDocPropertyTags . length > 0 ) {
6175
- const pos = typedefTag . jsDocPropertyTags [ 0 ] . pos ;
6176
- const end = typedefTag . jsDocPropertyTags [ typedefTag . jsDocPropertyTags . length - 1 ] . end ;
6177
- const jsdocTypeLiteral = < JSDocTypeLiteral > createNode ( SyntaxKind . JSDocTypeLiteral , pos ) ;
6178
- jsdocTypeLiteral . members = < NodeArray < JSDocPropertyTag > > [ ] ;
6179
- addRange ( jsdocTypeLiteral . members , typedefTag . jsDocPropertyTags ) ;
6180
- typedefTag . type = finishNode ( jsdocTypeLiteral , end ) ;
6181
- }
6182
- }
6183
-
6184
- addTag ( finishNode ( currentParentJSDocTag , currentParentJSDocTagEnd ) ) ;
6185
- currentParentJSDocTag = undefined ;
6186
- currentParentJSDocTagEnd = undefined ;
6187
- }
6188
-
6189
6148
function parseTag ( ) : void {
6190
6149
Debug . assert ( token === SyntaxKind . AtToken ) ;
6191
6150
const atToken = createNode ( SyntaxKind . AtToken , scanner . getTokenPos ( ) ) ;
@@ -6198,30 +6157,22 @@ namespace ts {
6198
6157
}
6199
6158
6200
6159
const tag = handleTag ( atToken , tagName ) || handleUnknownTag ( atToken , tagName ) ;
6201
- if ( ! currentParentJSDocTag ) {
6202
- addTag ( tag ) ;
6203
- }
6160
+ addTag ( tag ) ;
6204
6161
}
6205
6162
6206
6163
function handleTag ( atToken : Node , tagName : Identifier ) : JSDocTag {
6207
6164
if ( tagName ) {
6208
6165
switch ( tagName . text ) {
6209
6166
case "param" :
6210
- finishCurrentParentTag ( ) ;
6211
6167
return handleParamTag ( atToken , tagName ) ;
6212
6168
case "return" :
6213
6169
case "returns" :
6214
- finishCurrentParentTag ( ) ;
6215
6170
return handleReturnTag ( atToken , tagName ) ;
6216
6171
case "template" :
6217
- finishCurrentParentTag ( ) ;
6218
6172
return handleTemplateTag ( atToken , tagName ) ;
6219
6173
case "type" :
6220
- // @typedef tag is allowed to have one @type tag, therefore seeing
6221
- // a @type tag may not indicate the end of the current parent tag.
6222
6174
return handleTypeTag ( atToken , tagName ) ;
6223
6175
case "typedef" :
6224
- finishCurrentParentTag ( ) ;
6225
6176
return handleTypedefTag ( atToken , tagName ) ;
6226
6177
case "property" :
6227
6178
case "prop" :
@@ -6251,25 +6202,6 @@ namespace ts {
6251
6202
}
6252
6203
}
6253
6204
6254
- function addToCurrentParentTag ( tag : JSDocTag ) : void {
6255
- if ( ! currentParentJSDocTag ) {
6256
- return ;
6257
- }
6258
- switch ( tag . kind ) {
6259
- case SyntaxKind . JSDocPropertyTag :
6260
- if ( ! currentParentJSDocTag . jsDocPropertyTags ) {
6261
- currentParentJSDocTag . jsDocPropertyTags = < NodeArray < JSDocPropertyTag > > [ ] ;
6262
- }
6263
- currentParentJSDocTag . jsDocPropertyTags . push ( < JSDocPropertyTag > tag ) ;
6264
- break ;
6265
- case SyntaxKind . JSDocTypeTag :
6266
- if ( ! currentParentJSDocTag . jsDocTypeTag ) {
6267
- currentParentJSDocTag . jsDocTypeTag = < JSDocTypeTag > tag ;
6268
- }
6269
- break ;
6270
- }
6271
- }
6272
-
6273
6205
function tryParseTypeExpression ( ) : JSDocTypeExpression {
6274
6206
if ( token !== SyntaxKind . OpenBraceToken ) {
6275
6207
return undefined ;
@@ -6349,28 +6281,10 @@ namespace ts {
6349
6281
result . atToken = atToken ;
6350
6282
result . tagName = tagName ;
6351
6283
result . typeExpression = tryParseTypeExpression ( ) ;
6352
- result = finishNode ( result ) ;
6353
-
6354
- if ( currentParentJSDocTag && currentParentJSDocTag . kind === SyntaxKind . JSDocTypedefTag ) {
6355
- const parentTag = < JSDocTypedefTag > currentParentJSDocTag ;
6356
- if ( ! parentTag . typeExpression && ! parentTag . jsDocTypeTag ) {
6357
- parentTag . jsDocTypeTag = result ;
6358
- currentParentJSDocTagEnd = scanner . getStartPos ( ) ;
6359
- return result ;
6360
- }
6361
- }
6362
- // If this @type tag is not part of the current parent tag, then
6363
- // it denotes the end of the current parent tag.
6364
- finishCurrentParentTag ( ) ;
6365
- return result ;
6284
+ return finishNode ( result ) ;
6366
6285
}
6367
6286
6368
6287
function handlePropertyTag ( atToken : Node , tagName : Identifier ) : JSDocPropertyTag {
6369
- if ( ! currentParentJSDocTag ) {
6370
- parseErrorAtPosition ( tagName . pos , scanner . getTokenPos ( ) - tagName . pos , Diagnostics . _0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag , tagName . text ) ;
6371
- return undefined ;
6372
- }
6373
-
6374
6288
const typeExpression = tryParseTypeExpression ( ) ;
6375
6289
skipWhitespace ( ) ;
6376
6290
const name = parseJSDocIdentifierName ( ) ;
@@ -6384,12 +6298,7 @@ namespace ts {
6384
6298
result . tagName = tagName ;
6385
6299
result . name = name ;
6386
6300
result . typeExpression = typeExpression ;
6387
- result . type = typeExpression . type ;
6388
- result = finishNode ( result ) ;
6389
-
6390
- addToCurrentParentTag ( result ) ;
6391
- currentParentJSDocTagEnd = scanner . getStartPos ( ) ;
6392
- return undefined ;
6301
+ return finishNode ( result ) ;
6393
6302
}
6394
6303
6395
6304
function handleTypedefTag ( atToken : Node , tagName : Identifier ) : JSDocTypedefTag {
@@ -6413,32 +6322,100 @@ namespace ts {
6413
6322
}
6414
6323
}
6415
6324
6416
- const result = < JSDocTypedefTag > createNode ( SyntaxKind . JSDocTypedefTag , atToken . pos ) ;
6417
- result . atToken = atToken ;
6418
- result . tagName = tagName ;
6419
- result . name = name ;
6420
- result . typeExpression = typeExpression ;
6325
+ const typedefTag = < JSDocTypedefTag > createNode ( SyntaxKind . JSDocTypedefTag , atToken . pos ) ;
6326
+ typedefTag . atToken = atToken ;
6327
+ typedefTag . tagName = tagName ;
6328
+ typedefTag . name = name ;
6329
+ typedefTag . typeExpression = typeExpression ;
6421
6330
6422
- if ( typeExpression && typeExpression . type . kind === SyntaxKind . JSDocTypeReference ) {
6423
- const jsDocTypeReference = < JSDocTypeReference > typeExpression . type ;
6424
- if ( jsDocTypeReference . name . kind === SyntaxKind . Identifier ) {
6425
- const name = < Identifier > jsDocTypeReference . name ;
6426
- if ( name . text === "Object" ) {
6427
- currentParentJSDocTag = result ;
6331
+ if ( typeExpression ) {
6332
+ if ( typeExpression . type . kind === SyntaxKind . JSDocTypeReference ) {
6333
+ const jsDocTypeReference = < JSDocTypeReference > typeExpression . type ;
6334
+ if ( jsDocTypeReference . name . kind === SyntaxKind . Identifier ) {
6335
+ const name = < Identifier > jsDocTypeReference . name ;
6336
+ if ( name . text === "Object" ) {
6337
+ typedefTag . type = scanChildTags ( ) ;
6338
+ }
6428
6339
}
6429
6340
}
6341
+ if ( ! typedefTag . type ) {
6342
+ typedefTag . type = typeExpression . type ;
6343
+ }
6430
6344
}
6431
- else if ( ! typeExpression ) {
6432
- currentParentJSDocTag = result ;
6345
+ else {
6346
+ typedefTag . type = scanChildTags ( ) ;
6433
6347
}
6434
6348
6435
- if ( ! currentParentJSDocTag ) {
6436
- result . type = result . typeExpression . type ;
6437
- return finishNode ( result ) ;
6349
+ return finishNode ( typedefTag ) ;
6350
+
6351
+ function scanChildTags ( ) : JSDocTypeLiteral {
6352
+ const jsDocTypeLiteral = < JSDocTypeLiteral > createNode ( SyntaxKind . JSDocTypeLiteral , scanner . getStartPos ( ) ) ;
6353
+ let resumePos = scanner . getStartPos ( ) ;
6354
+ let canParseTag = true ;
6355
+ let seenAsterisk = false ;
6356
+ let parentTagTerminated = false ;
6357
+
6358
+ nextJSDocToken ( ) ;
6359
+ while ( token !== SyntaxKind . EndOfFileToken && ! parentTagTerminated ) {
6360
+ nextJSDocToken ( ) ;
6361
+ switch ( token ) {
6362
+ case SyntaxKind . AtToken :
6363
+ if ( canParseTag ) {
6364
+ parentTagTerminated = ! tryParseChildTag ( jsDocTypeLiteral ) ;
6365
+ }
6366
+ seenAsterisk = false ;
6367
+ break ;
6368
+ case SyntaxKind . NewLineTrivia :
6369
+ resumePos = scanner . getStartPos ( ) - 1 ;
6370
+ canParseTag = true ;
6371
+ seenAsterisk = false ;
6372
+ break ;
6373
+ case SyntaxKind . AsteriskToken :
6374
+ if ( seenAsterisk ) {
6375
+ canParseTag = false ;
6376
+ }
6377
+ seenAsterisk = true ;
6378
+ break ;
6379
+ case SyntaxKind . Identifier :
6380
+ canParseTag = false ;
6381
+ case SyntaxKind . EndOfFileToken :
6382
+ break ;
6383
+ }
6384
+ }
6385
+ scanner . setTextPos ( resumePos ) ;
6386
+ return finishNode ( jsDocTypeLiteral ) ;
6438
6387
}
6388
+ }
6439
6389
6440
- currentParentJSDocTagEnd = scanner . getStartPos ( ) ;
6441
- return undefined ;
6390
+ function tryParseChildTag ( parentTag : JSDocTypeLiteral ) : boolean {
6391
+ Debug . assert ( token === SyntaxKind . AtToken ) ;
6392
+ const atToken = createNode ( SyntaxKind . AtToken , scanner . getStartPos ( ) ) ;
6393
+ atToken . end = scanner . getTextPos ( ) ;
6394
+ nextJSDocToken ( ) ;
6395
+
6396
+ const tagName = parseJSDocIdentifierName ( ) ;
6397
+ if ( ! tagName ) {
6398
+ return false ;
6399
+ }
6400
+
6401
+ switch ( tagName . text ) {
6402
+ case "type" :
6403
+ if ( parentTag . jsDocTypeTag ) {
6404
+ // already has a @type tag, terminate the parent tag now.
6405
+ return false ;
6406
+ }
6407
+ parentTag . jsDocTypeTag = handleTypeTag ( atToken , tagName ) ;
6408
+ return true ;
6409
+ case "prop" :
6410
+ case "property" :
6411
+ if ( ! parentTag . jsDocPropertyTags ) {
6412
+ parentTag . jsDocPropertyTags = < NodeArray < JSDocPropertyTag > > [ ] ;
6413
+ }
6414
+ const propertyTag = handlePropertyTag ( atToken , tagName ) ;
6415
+ parentTag . jsDocPropertyTags . push ( propertyTag ) ;
6416
+ return true ;
6417
+ }
6418
+ return false ;
6442
6419
}
6443
6420
6444
6421
function handleTemplateTag ( atToken : Node , tagName : Identifier ) : JSDocTemplateTag {
0 commit comments