@@ -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,34 +6157,23 @@ 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
- case "property" :
6227
- case "prop" :
6228
- return handlePropertyTag ( atToken , tagName ) ;
6229
6177
}
6230
6178
}
6231
6179
@@ -6251,25 +6199,6 @@ namespace ts {
6251
6199
}
6252
6200
}
6253
6201
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
6202
function tryParseTypeExpression ( ) : JSDocTypeExpression {
6274
6203
if ( token !== SyntaxKind . OpenBraceToken ) {
6275
6204
return undefined ;
@@ -6345,32 +6274,14 @@ namespace ts {
6345
6274
parseErrorAtPosition ( tagName . pos , scanner . getTokenPos ( ) - tagName . pos , Diagnostics . _0_tag_already_specified , tagName . text ) ;
6346
6275
}
6347
6276
6348
- let result = < JSDocTypeTag > createNode ( SyntaxKind . JSDocTypeTag , atToken . pos ) ;
6277
+ const result = < JSDocTypeTag > createNode ( SyntaxKind . JSDocTypeTag , atToken . pos ) ;
6349
6278
result . atToken = atToken ;
6350
6279
result . tagName = tagName ;
6351
6280
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 ;
6281
+ return finishNode ( result ) ;
6366
6282
}
6367
6283
6368
6284
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
6285
const typeExpression = tryParseTypeExpression ( ) ;
6375
6286
skipWhitespace ( ) ;
6376
6287
const name = parseJSDocIdentifierName ( ) ;
@@ -6379,17 +6290,12 @@ namespace ts {
6379
6290
return undefined ;
6380
6291
}
6381
6292
6382
- let result = < JSDocPropertyTag > createNode ( SyntaxKind . JSDocPropertyTag , atToken . pos ) ;
6293
+ const result = < JSDocPropertyTag > createNode ( SyntaxKind . JSDocPropertyTag , atToken . pos ) ;
6383
6294
result . atToken = atToken ;
6384
6295
result . tagName = tagName ;
6385
6296
result . name = name ;
6386
6297
result . typeExpression = typeExpression ;
6387
- result . type = typeExpression . type ;
6388
- result = finishNode ( result ) ;
6389
-
6390
- addToCurrentParentTag ( result ) ;
6391
- currentParentJSDocTagEnd = scanner . getStartPos ( ) ;
6392
- return undefined ;
6298
+ return finishNode ( result ) ;
6393
6299
}
6394
6300
6395
6301
function handleTypedefTag ( atToken : Node , tagName : Identifier ) : JSDocTypedefTag {
@@ -6413,32 +6319,99 @@ namespace ts {
6413
6319
}
6414
6320
}
6415
6321
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 ;
6322
+ const typedefTag = < JSDocTypedefTag > createNode ( SyntaxKind . JSDocTypedefTag , atToken . pos ) ;
6323
+ typedefTag . atToken = atToken ;
6324
+ typedefTag . tagName = tagName ;
6325
+ typedefTag . name = name ;
6326
+ typedefTag . typeExpression = typeExpression ;
6421
6327
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 ;
6328
+ if ( typeExpression ) {
6329
+ if ( typeExpression . type . kind === SyntaxKind . JSDocTypeReference ) {
6330
+ const jsDocTypeReference = < JSDocTypeReference > typeExpression . type ;
6331
+ if ( jsDocTypeReference . name . kind === SyntaxKind . Identifier ) {
6332
+ const name = < Identifier > jsDocTypeReference . name ;
6333
+ if ( name . text === "Object" ) {
6334
+ typedefTag . type = scanChildTags ( ) ;
6335
+ }
6428
6336
}
6429
6337
}
6338
+ if ( ! typedefTag . type ) {
6339
+ typedefTag . type = typeExpression . type ;
6340
+ }
6341
+ }
6342
+ else {
6343
+ typedefTag . type = scanChildTags ( ) ;
6430
6344
}
6431
- else if ( ! typeExpression ) {
6432
- currentParentJSDocTag = result ;
6345
+
6346
+ return finishNode ( typedefTag ) ;
6347
+
6348
+ function scanChildTags ( ) : JSDocTypeLiteral {
6349
+ const jsDocTypeLiteral = < JSDocTypeLiteral > createNode ( SyntaxKind . JSDocTypeLiteral , scanner . getStartPos ( ) ) ;
6350
+ let resumePos = scanner . getStartPos ( ) ;
6351
+ let canParseTag = true ;
6352
+ let seenAsterisk = false ;
6353
+ let parentTagTerminated = false ;
6354
+
6355
+ while ( token !== SyntaxKind . EndOfFileToken && ! parentTagTerminated ) {
6356
+ nextJSDocToken ( ) ;
6357
+ switch ( token ) {
6358
+ case SyntaxKind . AtToken :
6359
+ if ( canParseTag ) {
6360
+ parentTagTerminated = ! tryParseChildTag ( jsDocTypeLiteral ) ;
6361
+ }
6362
+ seenAsterisk = false ;
6363
+ break ;
6364
+ case SyntaxKind . NewLineTrivia :
6365
+ resumePos = scanner . getStartPos ( ) - 1 ;
6366
+ canParseTag = true ;
6367
+ seenAsterisk = false ;
6368
+ break ;
6369
+ case SyntaxKind . AsteriskToken :
6370
+ if ( seenAsterisk ) {
6371
+ canParseTag = false ;
6372
+ }
6373
+ seenAsterisk = true ;
6374
+ break ;
6375
+ case SyntaxKind . Identifier :
6376
+ canParseTag = false ;
6377
+ case SyntaxKind . EndOfFileToken :
6378
+ break ;
6379
+ }
6380
+ }
6381
+ scanner . setTextPos ( resumePos ) ;
6382
+ return finishNode ( jsDocTypeLiteral ) ;
6433
6383
}
6384
+ }
6385
+
6386
+ function tryParseChildTag ( parentTag : JSDocTypeLiteral ) : boolean {
6387
+ Debug . assert ( token === SyntaxKind . AtToken ) ;
6388
+ const atToken = createNode ( SyntaxKind . AtToken , scanner . getStartPos ( ) ) ;
6389
+ atToken . end = scanner . getTextPos ( ) ;
6390
+ nextJSDocToken ( ) ;
6434
6391
6435
- if ( ! currentParentJSDocTag ) {
6436
- result . type = result . typeExpression . type ;
6437
- return finishNode ( result ) ;
6392
+ const tagName = parseJSDocIdentifierName ( ) ;
6393
+ if ( ! tagName ) {
6394
+ return false ;
6438
6395
}
6439
6396
6440
- currentParentJSDocTagEnd = scanner . getStartPos ( ) ;
6441
- return undefined ;
6397
+ switch ( tagName . text ) {
6398
+ case "type" :
6399
+ if ( parentTag . jsDocTypeTag ) {
6400
+ // already has a @type tag, terminate the parent tag now.
6401
+ return false ;
6402
+ }
6403
+ parentTag . jsDocTypeTag = handleTypeTag ( atToken , tagName ) ;
6404
+ return true ;
6405
+ case "prop" :
6406
+ case "property" :
6407
+ if ( ! parentTag . jsDocPropertyTags ) {
6408
+ parentTag . jsDocPropertyTags = < NodeArray < JSDocPropertyTag > > [ ] ;
6409
+ }
6410
+ const propertyTag = handlePropertyTag ( atToken , tagName ) ;
6411
+ parentTag . jsDocPropertyTags . push ( propertyTag ) ;
6412
+ return true ;
6413
+ }
6414
+ return false ;
6442
6415
}
6443
6416
6444
6417
function handleTemplateTag ( atToken : Node , tagName : Identifier ) : JSDocTemplateTag {
0 commit comments