@@ -1491,6 +1491,8 @@ namespace Parser {
1491
1491
var identifiers: Map<string, string>;
1492
1492
var identifierCount: number;
1493
1493
1494
+ // TODO(jakebailey): This type is a lie; this value actually contains the result
1495
+ // of ORing a bunch of `1 << ParsingContext.XYZ`.
1494
1496
var parsingContext: ParsingContext;
1495
1497
1496
1498
var notParenthesizedArrow: Set<number> | undefined;
@@ -2872,9 +2874,13 @@ namespace Parser {
2872
2874
return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
2873
2875
case ParsingContext.JsxChildren:
2874
2876
return true;
2877
+ case ParsingContext.JSDocComment:
2878
+ return true;
2879
+ case ParsingContext.Count:
2880
+ return Debug.fail("ParsingContext.Count used as a context"); // Not a real context, only a marker.
2881
+ default:
2882
+ Debug.assertNever(parsingContext, "Non-exhaustive case in 'isListElement'.");
2875
2883
}
2876
-
2877
- return Debug.fail("Non-exhaustive case in 'isListElement'.");
2878
2884
}
2879
2885
2880
2886
function isValidHeritageClauseObjectLiteral() {
@@ -3010,6 +3016,9 @@ namespace Parser {
3010
3016
3011
3017
// True if positioned at element or terminator of the current list or any enclosing list
3012
3018
function isInSomeParsingContext(): boolean {
3019
+ // We should be in at least one parsing context, be it SourceElements while parsing
3020
+ // a SourceFile, or JSDocComment when lazily parsing JSDoc.
3021
+ Debug.assert(parsingContext, "Missing parsing context");
3013
3022
for (let kind = 0; kind < ParsingContext.Count; kind++) {
3014
3023
if (parsingContext & (1 << kind)) {
3015
3024
if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) {
@@ -3385,6 +3394,7 @@ namespace Parser {
3385
3394
case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3386
3395
case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3387
3396
case ParsingContext.AssertEntries: return parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected); // AssertionKey.
3397
+ case ParsingContext.JSDocComment: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3388
3398
case ParsingContext.Count: return Debug.fail("ParsingContext.Count used as a context"); // Not a real context, only a marker.
3389
3399
default: Debug.assertNever(context);
3390
3400
}
@@ -7289,6 +7299,8 @@ namespace Parser {
7289
7299
7290
7300
function tryReuseAmbientDeclaration(pos: number): Statement | undefined {
7291
7301
return doInsideOfContext(NodeFlags.Ambient, () => {
7302
+ // TODO(jakebailey): this is totally wrong; `parsingContext` is the result of ORing a bunch of `1 << ParsingContext.XYZ`.
7303
+ // The enum should really be a bunch of flags.
7292
7304
const node = currentNode(parsingContext, pos);
7293
7305
if (node) {
7294
7306
return consumeNode(node) as Statement;
@@ -8492,7 +8504,8 @@ namespace Parser {
8492
8504
TupleElementTypes, // Element types in tuple element type list
8493
8505
HeritageClauses, // Heritage clauses for a class or interface declaration.
8494
8506
ImportOrExportSpecifiers, // Named import clause's import specifier list,
8495
- AssertEntries, // Import entries list.
8507
+ AssertEntries, // Import entries list.
8508
+ JSDocComment, // Parsing via JSDocParser
8496
8509
Count // Number of parsing contexts
8497
8510
}
8498
8511
@@ -8598,6 +8611,9 @@ namespace Parser {
8598
8611
}
8599
8612
8600
8613
function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
8614
+ const saveParsingContext = parsingContext;
8615
+ parsingContext |= 1 << ParsingContext.JSDocComment;
8616
+
8601
8617
const content = sourceText;
8602
8618
const end = length === undefined ? content.length : start + length;
8603
8619
length = end - start;
@@ -8620,7 +8636,11 @@ namespace Parser {
8620
8636
const parts: JSDocComment[] = [];
8621
8637
8622
8638
// + 3 for leading /**, - 5 in total for /** */
8623
- return scanner.scanRange(start + 3, length - 5, () => {
8639
+ const result = scanner.scanRange(start + 3, length - 5, doJSDocScan);
8640
+ parsingContext = saveParsingContext;
8641
+ return result;
8642
+
8643
+ function doJSDocScan() {
8624
8644
// Initially we can parse out a tag. We also have seen a starting asterisk.
8625
8645
// This is so that /** * @type */ doesn't parse.
8626
8646
let state = JSDocState.SawAsterisk;
@@ -8726,7 +8746,7 @@ namespace Parser {
8726
8746
if (parts.length && tags) Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set");
8727
8747
const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd);
8728
8748
return finishNode(factory.createJSDocComment(parts.length ? createNodeArray(parts, start, commentsPos) : trimmedComments.length ? trimmedComments : undefined, tagsArray), start, end);
8729
- });
8749
+ }
8730
8750
8731
8751
function removeLeadingNewlines(comments: string[]) {
8732
8752
while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) {
0 commit comments