diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 3ce7f411e24..f1221883bde 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5492,10 +5492,22 @@ namespace ts { } function parseDeclaration(): Statement { + const modifiers = lookAhead(() => (parseDecorators(), parseModifiers())); + // `parseListElement` attempted to get the reused node at this position, + // but the ambient context flag was not yet set, so the node appeared + // not reusable in that context. + const isAmbient = some(modifiers, isDeclareModifier); + if (isAmbient) { + const node = tryReuseAmbientDeclaration(); + if (node) { + return node; + } + } + const node = createNodeWithJSDoc(SyntaxKind.Unknown); node.decorators = parseDecorators(); node.modifiers = parseModifiers(); - if (some(node.modifiers, isDeclareModifier)) { + if (isAmbient) { for (const m of node.modifiers!) { m.flags |= NodeFlags.Ambient; } @@ -5506,6 +5518,15 @@ namespace ts { } } + function tryReuseAmbientDeclaration(): Statement | undefined { + return doInsideOfContext(NodeFlags.Ambient, () => { + const node = currentNode(parsingContext); + if (node) { + return consumeNode(node) as Statement; + } + }); + } + function parseDeclarationWorker(node: Statement): Statement { switch (token()) { case SyntaxKind.VarKeyword: diff --git a/src/testRunner/unittests/incrementalParser.ts b/src/testRunner/unittests/incrementalParser.ts index 8af44494803..7011f118a00 100644 --- a/src/testRunner/unittests/incrementalParser.ts +++ b/src/testRunner/unittests/incrementalParser.ts @@ -671,7 +671,7 @@ module m3 { }\ const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "{"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); }); it("Removing block around function declarations", () => { @@ -680,7 +680,7 @@ module m3 { }\ const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, "{".length); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); }); it("Moving methods from class to object literal", () => {