@@ -1081,6 +1081,10 @@ namespace ts {
1081
1081
return currentToken = scanner . scan ( ) ;
1082
1082
}
1083
1083
1084
+ function nextTokenJSDoc ( ) : JSDocSyntaxKind {
1085
+ return currentToken = scanner . scanJsDocToken ( ) ;
1086
+ }
1087
+
1084
1088
function reScanGreaterToken ( ) : SyntaxKind {
1085
1089
return currentToken = scanner . reScanGreaterToken ( ) ;
1086
1090
}
@@ -1198,6 +1202,15 @@ namespace ts {
1198
1202
return false ;
1199
1203
}
1200
1204
1205
+ function parseExpectedJSDoc ( kind : JSDocSyntaxKind ) {
1206
+ if ( token ( ) === kind ) {
1207
+ nextTokenJSDoc ( ) ;
1208
+ return true ;
1209
+ }
1210
+ parseErrorAtCurrentToken ( Diagnostics . _0_expected , tokenToString ( kind ) ) ;
1211
+ return false ;
1212
+ }
1213
+
1201
1214
function parseOptional ( t : SyntaxKind ) : boolean {
1202
1215
if ( token ( ) === t ) {
1203
1216
nextToken ( ) ;
@@ -1214,18 +1227,38 @@ namespace ts {
1214
1227
return undefined ;
1215
1228
}
1216
1229
1230
+ function parseOptionalTokenJSDoc < TKind extends JSDocSyntaxKind > ( t : TKind ) : Token < TKind > ;
1231
+ function parseOptionalTokenJSDoc ( t : JSDocSyntaxKind ) : Node | undefined {
1232
+ if ( token ( ) === t ) {
1233
+ return parseTokenNodeJSDoc ( ) ;
1234
+ }
1235
+ return undefined ;
1236
+ }
1237
+
1217
1238
function parseExpectedToken < TKind extends SyntaxKind > ( t : TKind , diagnosticMessage ?: DiagnosticMessage , arg0 ?: any ) : Token < TKind > ;
1218
1239
function parseExpectedToken ( t : SyntaxKind , diagnosticMessage ?: DiagnosticMessage , arg0 ?: any ) : Node {
1219
1240
return parseOptionalToken ( t ) ||
1220
1241
createMissingNode ( t , /*reportAtCurrentPosition*/ false , diagnosticMessage || Diagnostics . _0_expected , arg0 || tokenToString ( t ) ) ;
1221
1242
}
1222
1243
1244
+ function parseExpectedTokenJSDoc < TKind extends JSDocSyntaxKind > ( t : TKind ) : Token < TKind > ;
1245
+ function parseExpectedTokenJSDoc ( t : JSDocSyntaxKind ) : Node {
1246
+ return parseOptionalTokenJSDoc ( t ) ||
1247
+ createMissingNode ( t , /*reportAtCurrentPosition*/ false , Diagnostics . _0_expected , tokenToString ( t ) ) ;
1248
+ }
1249
+
1223
1250
function parseTokenNode < T extends Node > ( ) : T {
1224
1251
const node = < T > createNode ( token ( ) ) ;
1225
1252
nextToken ( ) ;
1226
1253
return finishNode ( node ) ;
1227
1254
}
1228
1255
1256
+ function parseTokenNodeJSDoc < T extends Node > ( ) : T {
1257
+ const node = < T > createNode ( token ( ) ) ;
1258
+ nextTokenJSDoc ( ) ;
1259
+ return finishNode ( node ) ;
1260
+ }
1261
+
1229
1262
function canParseSemicolon ( ) {
1230
1263
// If there's a real semicolon, then we can always parse it out.
1231
1264
if ( token ( ) === SyntaxKind . SemicolonToken ) {
@@ -6345,7 +6378,7 @@ namespace ts {
6345
6378
const hasBrace = ( mayOmitBraces ? parseOptional : parseExpected ) ( SyntaxKind . OpenBraceToken ) ;
6346
6379
result . type = doInsideOfContext ( NodeFlags . JSDoc , parseJSDocType ) ;
6347
6380
if ( ! mayOmitBraces || hasBrace ) {
6348
- parseExpected ( SyntaxKind . CloseBraceToken ) ;
6381
+ parseExpectedJSDoc ( SyntaxKind . CloseBraceToken ) ;
6349
6382
}
6350
6383
6351
6384
fixupParentReferences ( result ) ;
@@ -6432,7 +6465,7 @@ namespace ts {
6432
6465
indent += text . length ;
6433
6466
}
6434
6467
6435
- nextJSDocToken ( ) ;
6468
+ nextTokenJSDoc ( ) ;
6436
6469
while ( parseOptionalJsdoc ( SyntaxKind . WhitespaceTrivia ) ) ;
6437
6470
if ( parseOptionalJsdoc ( SyntaxKind . NewLineTrivia ) ) {
6438
6471
state = JSDocState . BeginningOfLine ;
@@ -6493,7 +6526,7 @@ namespace ts {
6493
6526
pushComment ( scanner . getTokenText ( ) ) ;
6494
6527
break ;
6495
6528
}
6496
- nextJSDocToken ( ) ;
6529
+ nextTokenJSDoc ( ) ;
6497
6530
}
6498
6531
removeLeadingNewlines ( comments ) ;
6499
6532
removeTrailingWhitespace ( comments ) ;
@@ -6522,7 +6555,7 @@ namespace ts {
6522
6555
function isNextNonwhitespaceTokenEndOfFile ( ) : boolean {
6523
6556
// We must use infinite lookahead, as there could be any number of newlines :(
6524
6557
while ( true ) {
6525
- nextJSDocToken ( ) ;
6558
+ nextTokenJSDoc ( ) ;
6526
6559
if ( token ( ) === SyntaxKind . EndOfFileToken ) {
6527
6560
return true ;
6528
6561
}
@@ -6539,7 +6572,7 @@ namespace ts {
6539
6572
}
6540
6573
}
6541
6574
while ( token ( ) === SyntaxKind . WhitespaceTrivia || token ( ) === SyntaxKind . NewLineTrivia ) {
6542
- nextJSDocToken ( ) ;
6575
+ nextTokenJSDoc ( ) ;
6543
6576
}
6544
6577
}
6545
6578
@@ -6563,15 +6596,15 @@ namespace ts {
6563
6596
else if ( token ( ) === SyntaxKind . AsteriskToken ) {
6564
6597
precedingLineBreak = false ;
6565
6598
}
6566
- nextJSDocToken ( ) ;
6599
+ nextTokenJSDoc ( ) ;
6567
6600
}
6568
6601
return seenLineBreak ? indentText : "" ;
6569
6602
}
6570
6603
6571
6604
function parseTag ( margin : number ) {
6572
6605
Debug . assert ( token ( ) === SyntaxKind . AtToken ) ;
6573
6606
const start = scanner . getTokenPos ( ) ;
6574
- nextJSDocToken ( ) ;
6607
+ nextTokenJSDoc ( ) ;
6575
6608
6576
6609
const tagName = parseJSDocIdentifierName ( /*message*/ undefined ) ;
6577
6610
const indentText = skipWhitespaceOrAsterisk ( ) ;
@@ -6643,7 +6676,7 @@ namespace ts {
6643
6676
pushComment ( initialMargin ) ;
6644
6677
state = JSDocState . SavingComments ;
6645
6678
}
6646
- let tok = token ( ) as JsDocSyntaxKind ;
6679
+ let tok = token ( ) as JSDocSyntaxKind ;
6647
6680
loop: while ( true ) {
6648
6681
switch ( tok ) {
6649
6682
case SyntaxKind . NewLineTrivia :
@@ -6674,11 +6707,11 @@ namespace ts {
6674
6707
break ;
6675
6708
case SyntaxKind . OpenBraceToken :
6676
6709
state = JSDocState . SavingComments ;
6677
- if ( lookAhead ( ( ) => nextJSDocToken ( ) === SyntaxKind . AtToken && tokenIsIdentifierOrKeyword ( nextJSDocToken ( ) ) && scanner . getTokenText ( ) === "link" ) ) {
6710
+ if ( lookAhead ( ( ) => nextTokenJSDoc ( ) === SyntaxKind . AtToken && tokenIsIdentifierOrKeyword ( nextTokenJSDoc ( ) ) && scanner . getTokenText ( ) === "link" ) ) {
6678
6711
pushComment ( scanner . getTokenText ( ) ) ;
6679
- nextJSDocToken ( ) ;
6712
+ nextTokenJSDoc ( ) ;
6680
6713
pushComment ( scanner . getTokenText ( ) ) ;
6681
- nextJSDocToken ( ) ;
6714
+ nextTokenJSDoc ( ) ;
6682
6715
}
6683
6716
pushComment ( scanner . getTokenText ( ) ) ;
6684
6717
break ;
@@ -6696,7 +6729,7 @@ namespace ts {
6696
6729
pushComment ( scanner . getTokenText ( ) ) ;
6697
6730
break ;
6698
6731
}
6699
- tok = nextJSDocToken ( ) ;
6732
+ tok = nextTokenJSDoc ( ) ;
6700
6733
}
6701
6734
6702
6735
removeLeadingNewlines ( comments ) ;
@@ -6730,16 +6763,19 @@ namespace ts {
6730
6763
}
6731
6764
6732
6765
function parseBracketNameInPropertyAndParamTag ( ) : { name : EntityName , isBracketed : boolean } {
6733
- if ( token ( ) === SyntaxKind . NoSubstitutionTemplateLiteral ) {
6734
- // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
6735
- return { name : createIdentifier ( /*isIdentifier*/ true ) , isBracketed : false } ;
6736
- }
6737
6766
// Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
6738
- const isBracketed = parseOptional ( SyntaxKind . OpenBracketToken ) ;
6767
+ const isBracketed = parseOptionalJsdoc ( SyntaxKind . OpenBracketToken ) ;
6768
+ if ( isBracketed ) {
6769
+ skipWhitespace ( ) ;
6770
+ }
6771
+ // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
6772
+ const isBackquoted = parseOptionalJsdoc ( SyntaxKind . BacktickToken ) ;
6739
6773
const name = parseJSDocEntityName ( ) ;
6774
+ if ( isBackquoted ) {
6775
+ parseExpectedTokenJSDoc ( SyntaxKind . BacktickToken ) ;
6776
+ }
6740
6777
if ( isBracketed ) {
6741
6778
skipWhitespace ( ) ;
6742
-
6743
6779
// May have an optional default, e.g. '[foo = 42]'
6744
6780
if ( parseOptionalToken ( SyntaxKind . EqualsToken ) ) {
6745
6781
parseExpression ( ) ;
@@ -7022,7 +7058,7 @@ namespace ts {
7022
7058
let canParseTag = true ;
7023
7059
let seenAsterisk = false ;
7024
7060
while ( true ) {
7025
- switch ( nextJSDocToken ( ) ) {
7061
+ switch ( nextTokenJSDoc ( ) ) {
7026
7062
case SyntaxKind . AtToken :
7027
7063
if ( canParseTag ) {
7028
7064
const child = tryParseChildTag ( target , indent ) ;
@@ -7057,7 +7093,7 @@ namespace ts {
7057
7093
function tryParseChildTag ( target : PropertyLikeParse , indent : number ) : JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
7058
7094
Debug . assert ( token ( ) === SyntaxKind . AtToken ) ;
7059
7095
const start = scanner . getStartPos ( ) ;
7060
- nextJSDocToken ( ) ;
7096
+ nextTokenJSDoc ( ) ;
7061
7097
7062
7098
const tagName = parseJSDocIdentifierName ( ) ;
7063
7099
skipWhitespace ( ) ;
@@ -7109,13 +7145,9 @@ namespace ts {
7109
7145
return result ;
7110
7146
}
7111
7147
7112
- function nextJSDocToken ( ) : JsDocSyntaxKind {
7113
- return currentToken = scanner . scanJSDocToken ( ) ;
7114
- }
7115
-
7116
- function parseOptionalJsdoc ( t : JsDocSyntaxKind ) : boolean {
7148
+ function parseOptionalJsdoc ( t : JSDocSyntaxKind ) : boolean {
7117
7149
if ( token ( ) === t ) {
7118
- nextJSDocToken ( ) ;
7150
+ nextTokenJSDoc ( ) ;
7119
7151
return true ;
7120
7152
}
7121
7153
return false ;
@@ -7150,7 +7182,7 @@ namespace ts {
7150
7182
result . escapedText = escapeLeadingUnderscores ( scanner . getTokenText ( ) ) ;
7151
7183
finishNode ( result , end ) ;
7152
7184
7153
- nextJSDocToken ( ) ;
7185
+ nextTokenJSDoc ( ) ;
7154
7186
return result ;
7155
7187
}
7156
7188
}
0 commit comments