From f2de4508dfcb72ca33964d6cb4daea1065051214 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 26 Sep 2016 11:20:24 -0700 Subject: [PATCH] Extract emit-specific properties into EmitNode --- src/compiler/binder.ts | 6 +- src/compiler/comments.ts | 20 +- src/compiler/core.ts | 67 +++- src/compiler/emitter.ts | 151 +++++--- src/compiler/factory.ts | 34 +- src/compiler/transformer.ts | 413 +++++++-------------- src/compiler/transformers/destructuring.ts | 12 +- src/compiler/transformers/es6.ts | 109 +++--- src/compiler/transformers/es7.ts | 4 + src/compiler/transformers/generators.ts | 15 +- src/compiler/transformers/jsx.ts | 4 + src/compiler/transformers/module/es6.ts | 4 + src/compiler/transformers/module/module.ts | 39 +- src/compiler/transformers/module/system.ts | 24 +- src/compiler/transformers/ts.ts | 74 ++-- src/compiler/types.ts | 16 +- 16 files changed, 492 insertions(+), 500 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 49434e80aba..e2d31162127 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2592,7 +2592,7 @@ namespace ts { } // Currently, we only support generators that were originally async function bodies. - if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) { + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { transformFlags |= TransformFlags.AssertGenerator; } @@ -2667,7 +2667,7 @@ namespace ts { // down-level generator. // Currently we do not support transforming any other generator fucntions // down level. - if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) { + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { transformFlags |= TransformFlags.AssertGenerator; } } @@ -2698,7 +2698,7 @@ namespace ts { // down-level generator. // Currently we do not support transforming any other generator fucntions // down level. - if (asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) { + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { transformFlags |= TransformFlags.AssertGenerator; } diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 1bca13a4bdb..f9f8e74d4ca 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -41,11 +41,11 @@ namespace ts { } if (node) { - const { pos, end } = node.commentRange || node; - const emitFlags = node.emitFlags; + const { pos, end } = getCommentRange(node); + const emitFlags = getEmitFlags(node); if ((pos < 0 && end < 0) || (pos === end)) { // Both pos and end are synthesized, so just emit the node without comments. - if (emitFlags & NodeEmitFlags.NoNestedComments) { + if (emitFlags & EmitFlags.NoNestedComments) { disableCommentsAndEmit(node, emitCallback); } else { @@ -58,8 +58,8 @@ namespace ts { } const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement; - const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0; - const skipTrailingComments = end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0; + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0; + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0; // Emit leading comments if the position is not synthesized and the node // has not opted out from emitting leading comments. @@ -90,7 +90,7 @@ namespace ts { performance.measure("commentTime", "preEmitNodeWithComment"); } - if (emitFlags & NodeEmitFlags.NoNestedComments) { + if (emitFlags & EmitFlags.NoNestedComments) { disableCommentsAndEmit(node, emitCallback); } else { @@ -125,9 +125,9 @@ namespace ts { } const { pos, end } = detachedRange; - const emitFlags = node.emitFlags; - const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0; - const skipTrailingComments = disabled || end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0; + const emitFlags = getEmitFlags(node); + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0; + const skipTrailingComments = disabled || end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0; if (!skipLeadingComments) { emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); @@ -137,7 +137,7 @@ namespace ts { performance.measure("commentTime", "preEmitBodyWithDetachedComments"); } - if (emitFlags & NodeEmitFlags.NoNestedComments) { + if (emitFlags & EmitFlags.NoNestedComments) { disableCommentsAndEmit(node, emitCallback); } else { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 72d05e1cfd7..6a37292c532 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -824,6 +824,72 @@ namespace ts { }; } + /** + * High-order function, creates a function that executes a function composition. + * For example, `chain(a, b)` is the equivalent of `x => ((a', b') => y => b'(a'(y)))(a(x), b(x))` + * + * @param args The functions to chain. + */ + export function chain(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U; + export function chain(a: (t: T) => (u: U) => U, b: (t: T) => (u: U) => U, c: (t: T) => (u: U) => U, d: (t: T) => (u: U) => U, e: (t: T) => (u: U) => U): (t: T) => (u: U) => U { + if (e) { + const args: ((t: T) => (u: U) => U)[] = []; + for (let i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + return t => compose(...map(args, f => f(t))); + } + else if (d) { + return t => compose(a(t), b(t), c(t), d(t)); + } + else if (c) { + return t => compose(a(t), b(t), c(t)); + } + else if (b) { + return t => compose(a(t), b(t)); + } + else if (a) { + return t => compose(a(t)); + } + else { + return t => u => u; + } + } + + /** + * High-order function, composes functions. Note that functions are composed inside-out; + * for example, `compose(a, b)` is the equivalent of `x => b(a(x))`. + * + * @param args The functions to compose. + */ + export function compose(...args: ((t: T) => T)[]): (t: T) => T; + export function compose(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T { + if (e) { + const args: ((t: T) => T)[] = []; + for (let i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + return t => reduceLeft<(t: T) => T, T>(args, (u, f) => f(u), t); + } + else if (d) { + return t => d(c(b(a(t)))); + } + else if (c) { + return t => c(b(a(t))); + } + else if (b) { + return t => b(a(t)); + } + else if (a) { + return t => a(t); + } + else { + return t => t; + } + } + function formatStringFromArgs(text: string, args: { [index: number]: any; }, baseIndex?: number): string { baseIndex = baseIndex || 0; @@ -1715,7 +1781,6 @@ namespace ts { this.transformFlags = TransformFlags.None; this.parent = undefined; this.original = undefined; - this.transformId = 0; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 14e743cf59f..5487057bbca 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -244,7 +244,6 @@ const _super = (function (geti, seti) { // Extract helpers from the result const { - getTokenSourceMapRange, isSubstitutionEnabled, isEmitNotificationEnabled, onSubstituteNode, @@ -351,7 +350,7 @@ const _super = (function (geti, seti) { currentFileIdentifiers = node.identifiers; sourceMap.setSourceFile(node); comments.setSourceFile(node); - emitNodeWithNotification(node, emitWorker); + emitNodeWithNotification(node, emitWithSubstitution); } /** @@ -361,7 +360,6 @@ const _super = (function (geti, seti) { emitNodeWithNotification(node, emitWithComments); } - /** * Emits a node with comments. * @@ -379,17 +377,37 @@ const _super = (function (geti, seti) { * and should only be called indirectly from emitWithComments. */ function emitWithSourceMap(node: Node) { - emitNodeWithSourceMap(node, emitWorker); + emitNodeWithSourceMap(node, emitWithSubstitution); } + /** + * Emits a node with possible substitution. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from emitWithSourceMap or + * emitIdentifierNameWithComments. + */ + function emitWithSubstitution(node: Node) { + emitNodeWithSubstitution(node, /*isExpression*/ false, emitWorker); + } + + /** + * Emits an IdentifierName. + */ function emitIdentifierName(node: Identifier) { if (node) { emitNodeWithNotification(node, emitIdentifierNameWithComments); } } + /** + * Emits an IdentifierName with possible comments. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from emitIdentifierName. + */ function emitIdentifierNameWithComments(node: Identifier) { - emitNodeWithComments(node, emitWorker); + emitNodeWithComments(node, emitWithSubstitution); } /** @@ -410,18 +428,30 @@ const _super = (function (geti, seti) { } /** - * Emits an expression with source maps. + * Emits an expression with possible source maps. * * NOTE: Do not call this method directly. It is part of the emitExpression pipeline * and should only be called indirectly from emitExpressionWithComments. */ function emitExpressionWithSourceMap(node: Expression) { - emitNodeWithSourceMap(node, emitExpressionWorker); + emitNodeWithSourceMap(node, emitExpressionWithSubstitution); } /** - * Emits a node with emit notification if available. + * Emits an expression with possible substitution. + * + * NOTE: Do not call this method directly. It is part of the emitExpression pipeline + * and should only be called indirectly from emitExpressionWithSourceMap or + * from emitWorker. */ + function emitExpressionWithSubstitution(node: Expression) { + emitNodeWithSubstitution(node, /*isExpression*/ true, emitExpressionWorker); + } + + /** + * Emits a node with possible emit notification. + */ + // TODO(rbuckton): Move this into transformer.ts function emitNodeWithNotification(node: Node, emitCallback: (node: Node) => void) { if (node) { if (isEmitNotificationEnabled(node)) { @@ -433,6 +463,10 @@ const _super = (function (geti, seti) { } } + /** + * Emits a node with possible source maps. + */ + // TODO(rbuckton): Move this into sourcemap.ts function emitNodeWithSourceMap(node: Node, emitCallback: (node: Node) => void) { if (node) { emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange); @@ -441,10 +475,6 @@ const _super = (function (geti, seti) { } } - function getSourceMapRange(node: Node) { - return node.sourceMapRange || node; - } - /** * Determines whether to skip leading comment emit for a node. * @@ -453,9 +483,10 @@ const _super = (function (geti, seti) { * * @param node A Node. */ + // TODO(rbuckton): Move this into comments.ts function shouldSkipLeadingCommentsForNode(node: Node) { return isNotEmittedStatement(node) - || (node.emitFlags & NodeEmitFlags.NoLeadingComments) !== 0; + || (getEmitFlags(node) & EmitFlags.NoLeadingComments) !== 0; } /** @@ -466,12 +497,12 @@ const _super = (function (geti, seti) { * * @param node A Node. */ + // TODO(rbuckton): Move this into sourcemap.ts function shouldSkipLeadingSourceMapForNode(node: Node) { return isNotEmittedStatement(node) - || (node.emitFlags & NodeEmitFlags.NoLeadingSourceMap) !== 0; + || (getEmitFlags(node) & EmitFlags.NoLeadingSourceMap) !== 0; } - /** * Determines whether to skip source map emit for the end position of a node. * @@ -480,9 +511,10 @@ const _super = (function (geti, seti) { * * @param node A Node. */ + // TODO(rbuckton): Move this into sourcemap.ts function shouldSkipTrailingSourceMapForNode(node: Node) { return isNotEmittedStatement(node) - || (node.emitFlags & NodeEmitFlags.NoTrailingSourceMap) !== 0; + || (getEmitFlags(node) & EmitFlags.NoTrailingSourceMap) !== 0; } /** @@ -490,15 +522,34 @@ const _super = (function (geti, seti) { * * We do not emit source maps for a node that has NodeEmitFlags.NoNestedSourceMaps. */ + // TODO(rbuckton): Move this into sourcemap.ts function shouldSkipSourceMapForChildren(node: Node) { - return (node.emitFlags & NodeEmitFlags.NoNestedSourceMaps) !== 0; + return (getEmitFlags(node) & EmitFlags.NoNestedSourceMaps) !== 0; } - function emitWorker(node: Node): void { - if (tryEmitSubstitute(node, emitWorker, /*isExpression*/ false)) { - return; + /** + * Emits a node with possible substitution. + */ + // TODO(rbuckton): Move this into transformer.ts + function emitNodeWithSubstitution(node: Node, isExpression: boolean, emitCallback: (node: Node) => void) { + if (isSubstitutionEnabled(node) && (getEmitFlags(node) & EmitFlags.NoSubstitution) === 0) { + const substitute = onSubstituteNode(node, isExpression); + if (substitute !== node) { + emitCallback(substitute); + return; + } } + emitCallback(node); + } + + /** + * Emits a node. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from emitNodeWithSubstitution. + */ + function emitWorker(node: Node): void { const kind = node.kind; switch (kind) { // Pseudo-literals @@ -749,15 +800,17 @@ const _super = (function (geti, seti) { } if (isExpression(node)) { - return emitExpressionWorker(node); + return emitExpressionWithSubstitution(node); } } + /** + * Emits an expression. + * + * NOTE: Do not call this method directly. It is part of the emitExpression pipeline + * and should only be called indirectly from emitExpressionWithNotification. + */ function emitExpressionWorker(node: Node) { - if (tryEmitSubstitute(node, emitExpressionWorker, /*isExpression*/ true)) { - return; - } - const kind = node.kind; switch (kind) { // Literals @@ -881,7 +934,7 @@ const _super = (function (geti, seti) { // function emitIdentifier(node: Identifier) { - if (node.emitFlags & NodeEmitFlags.UMDDefine) { + if (getEmitFlags(node) & EmitFlags.UMDDefine) { writeLines(umdHelper); } else { @@ -1154,7 +1207,7 @@ const _super = (function (geti, seti) { write("{}"); } else { - const indentedFlag = node.emitFlags & NodeEmitFlags.Indented; + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } @@ -1176,7 +1229,7 @@ const _super = (function (geti, seti) { let indentBeforeDot = false; let indentAfterDot = false; - if (!(node.emitFlags & NodeEmitFlags.NoIndentation)) { + if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { const dotRangeStart = node.expression.end; const dotRangeEnd = skipTrivia(currentText, node.expression.end) + 1; const dotToken = { kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd }; @@ -1419,7 +1472,7 @@ const _super = (function (geti, seti) { } function emitBlockStatements(node: Block) { - if (node.emitFlags & NodeEmitFlags.SingleLine) { + if (getEmitFlags(node) & EmitFlags.SingleLine) { emitList(node, node.statements, ListFormat.SingleLineBlockStatements); } else { @@ -1623,12 +1676,12 @@ const _super = (function (geti, seti) { const body = node.body; if (body) { if (isBlock(body)) { - const indentedFlag = node.emitFlags & NodeEmitFlags.Indented; + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } - if (node.emitFlags & NodeEmitFlags.ReuseTempVariableScope) { + if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { emitSignatureHead(node); emitBlockFunctionBody(node, body); } @@ -1672,7 +1725,7 @@ const _super = (function (geti, seti) { // * A non-synthesized body's start and end position are on different lines. // * Any statement in the body starts on a new line. - if (body.emitFlags & NodeEmitFlags.SingleLine) { + if (getEmitFlags(body) & EmitFlags.SingleLine) { return true; } @@ -1743,7 +1796,7 @@ const _super = (function (geti, seti) { write("class"); emitNodeWithPrefix(" ", node.name, emitIdentifierName); - const indentedFlag = node.emitFlags & NodeEmitFlags.Indented; + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } @@ -2077,7 +2130,7 @@ const _super = (function (geti, seti) { // but rather a trailing comment on the previous node. const initializer = node.initializer; if (!shouldSkipLeadingCommentsForNode(initializer)) { - const commentRange = initializer.commentRange || initializer; + const commentRange = getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); } @@ -2149,23 +2202,23 @@ const _super = (function (geti, seti) { } function emitHelpers(node: Node) { - const emitFlags = node.emitFlags; + const emitFlags = getEmitFlags(node); let helpersEmitted = false; - if (emitFlags & NodeEmitFlags.EmitEmitHelpers) { + if (emitFlags & EmitFlags.EmitEmitHelpers) { helpersEmitted = emitEmitHelpers(currentSourceFile); } - if (emitFlags & NodeEmitFlags.EmitExportStar) { + if (emitFlags & EmitFlags.EmitExportStar) { writeLines(exportStarHelper); helpersEmitted = true; } - if (emitFlags & NodeEmitFlags.EmitSuperHelper) { + if (emitFlags & EmitFlags.EmitSuperHelper) { writeLines(superHelper); helpersEmitted = true; } - if (emitFlags & NodeEmitFlags.EmitAdvancedSuperHelper) { + if (emitFlags & EmitFlags.EmitAdvancedSuperHelper) { writeLines(advancedSuperHelper); helpersEmitted = true; } @@ -2287,19 +2340,7 @@ const _super = (function (geti, seti) { } } - function tryEmitSubstitute(node: Node, emitNode: (node: Node) => void, isExpression: boolean) { - if (isSubstitutionEnabled(node) && (node.emitFlags & NodeEmitFlags.NoSubstitution) === 0) { - const substitute = onSubstituteNode(node, isExpression); - if (substitute !== node) { - substitute.emitFlags |= NodeEmitFlags.NoSubstitution; - emitNode(substitute); - return true; - } - } - - return false; - } - + // TODO(rbuckton): Move this into a transformer function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean { const constantValue = tryGetConstEnumValue(node); if (constantValue !== undefined) { @@ -2440,7 +2481,7 @@ const _super = (function (geti, seti) { } if (shouldEmitInterveningComments) { - const commentRange = child.commentRange || child; + const commentRange = getCommentRange(child); emitTrailingCommentsOfPosition(commentRange.pos); } else { @@ -2502,11 +2543,11 @@ const _super = (function (geti, seti) { } function shouldSkipLeadingSourceMapForToken(contextNode: Node) { - return (contextNode.emitFlags & NodeEmitFlags.NoTokenLeadingSourceMaps) !== 0; + return (getEmitFlags(contextNode) & EmitFlags.NoTokenLeadingSourceMaps) !== 0; } function shouldSkipTrailingSourceMapForToken(contextNode: Node) { - return (contextNode.emitFlags & NodeEmitFlags.NoTokenTrailingSourceMaps) !== 0; + return (getEmitFlags(contextNode) & EmitFlags.NoTokenTrailingSourceMaps) !== 0; } function writeTokenText(token: SyntaxKind, pos?: number) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 16eeb86f59a..c0565f6e91d 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -76,7 +76,7 @@ namespace ts { // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). const clone = createNode(node.kind, /*location*/ undefined, node.flags); - clone.original = node; + setOriginalNode(clone, node); for (const key in node) { if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { @@ -435,7 +435,7 @@ namespace ts { export function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange, flags?: NodeFlags) { const node = createNode(SyntaxKind.PropertyAccessExpression, location, flags); node.expression = parenthesizeForAccess(expression); - node.emitFlags = NodeEmitFlags.NoIndentation; + (node.emitNode || (node.emitNode = {})).flags |= EmitFlags.NoIndentation; node.name = typeof name === "string" ? createIdentifier(name) : name; return node; } @@ -444,7 +444,7 @@ namespace ts { if (node.expression !== expression || node.name !== name) { const propertyAccess = createPropertyAccess(expression, name, /*location*/ node, node.flags); // Because we are updating existed propertyAccess we want to inherit its emitFlags instead of using default from createPropertyAccess - propertyAccess.emitFlags = node.emitFlags; + (propertyAccess.emitNode || (propertyAccess.emitNode = {})).flags = getEmitFlags(node); return updateNode(propertyAccess, node); } return node; @@ -1551,7 +1551,7 @@ namespace ts { } else { const expression = isIdentifier(memberName) ? createPropertyAccess(target, memberName, location) : createElementAccess(target, memberName, location); - expression.emitFlags |= NodeEmitFlags.NoNestedSourceMaps; + (expression.emitNode || (expression.emitNode = {})).flags |= EmitFlags.NoNestedSourceMaps; return expression; } } @@ -1744,7 +1744,7 @@ namespace ts { ); // Mark this node as originally an async function - generatorFunc.emitFlags |= NodeEmitFlags.AsyncFunctionBody; + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody; return createCall( createHelperName(externalHelpersModuleName, "__awaiter"), @@ -2222,7 +2222,7 @@ namespace ts { target.push(startOnNewLine(createStatement(createLiteral("use strict")))); foundUseStrict = true; } - if (statement.emitFlags & NodeEmitFlags.CustomPrologue) { + if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { target.push(visitor ? visitNode(statement, visitor, isStatement) : statement); } else { @@ -2643,14 +2643,28 @@ namespace ts { export function setOriginalNode(node: T, original: Node): T { node.original = original; if (original) { - const { emitFlags, commentRange, sourceMapRange } = original; - if (emitFlags) node.emitFlags = emitFlags; - if (commentRange) node.commentRange = commentRange; - if (sourceMapRange) node.sourceMapRange = sourceMapRange; + const emitNode = original.emitNode; + if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); } return node; } + function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) { + const { flags, commentRange, sourceMapRange, tokenSourceMapRanges } = sourceEmitNode; + if (!destEmitNode && (flags || commentRange || sourceMapRange || tokenSourceMapRanges)) destEmitNode = {}; + if (flags) destEmitNode.flags = flags; + if (commentRange) destEmitNode.commentRange = commentRange; + if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; + if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); + return destEmitNode; + } + + function mergeTokenSourceMapRanges(sourceRanges: Map, destRanges: Map) { + if (!destRanges) destRanges = createMap(); + copyProperties(sourceRanges, destRanges); + return destRanges; + } + export function setTextRange(node: T, location: TextRange): T { if (location) { node.pos = location.pos; diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 6242a2f2347..8c6fae458f0 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -30,11 +30,6 @@ namespace ts { */ getSourceFiles(): SourceFile[]; - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange; - /** * Determines whether expression substitutions are enabled for the provided node. */ @@ -75,46 +70,6 @@ namespace ts { getEmitResolver(): EmitResolver; getEmitHost(): EmitHost; - /** - * Gets flags used to customize later transformations or emit. - */ - getNodeEmitFlags(node: Node): NodeEmitFlags; - - /** - * Sets flags used to customize later transformations or emit. - */ - setNodeEmitFlags(node: T, flags: NodeEmitFlags): T; - - /** - * Gets the TextRange to use for source maps for the node. - */ - getSourceMapRange(node: Node): TextRange; - - /** - * Sets the TextRange to use for source maps for the node. - */ - setSourceMapRange(node: T, range: TextRange): T; - - /** - * Gets the TextRange to use for source maps for a token of a node. - */ - getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange; - - /** - * Sets the TextRange to use for source maps for a token of a node. - */ - setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange): T; - - /** - * Gets the TextRange to use for comments for the node. - */ - getCommentRange(node: Node): TextRange; - - /** - * Sets the TextRange to use for comments for the node. - */ - setCommentRange(node: T, range: TextRange): T; - /** * Hoists a function declaration to the containing scope. */ @@ -187,12 +142,137 @@ namespace ts { } /** - * Tracks a monotonically increasing transformation id used to associate a node with a specific - * transformation. This ensures transient properties related to transformations can be safely - * stored on source tree nodes that may be reused across multiple transformations (such as - * with compile-on-save). + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. */ - let nextTransformId = 1; + export function disposeEmitNodes(sourceFile: SourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); + const emitNode = sourceFile && sourceFile.emitNode; + const annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (const node of annotatedNodes) { + node.emitNode = undefined; + } + } + } + + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + * + * @param node The node. + */ + function getOrCreateEmitNode(node: Node) { + if (!node.emitNode) { + if (isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === SyntaxKind.SourceFile) { + return node.emitNode = { annotatedNodes: [node] }; + } + + const sourceFile = getSourceFileOfNode(node); + getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); + } + + node.emitNode = {}; + } + + return node.emitNode; + } + + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + export function getEmitFlags(node: Node) { + const emitNode = node.emitNode; + return emitNode && emitNode.flags; + } + + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + export function setEmitFlags(node: T, emitFlags: EmitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + export function setSourceMapRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { + const emitNode = getOrCreateEmitNode(node); + const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = createMap()); + tokenSourceMapRanges[token] = range; + return node; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + export function setCommentRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + export function getCommentRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + export function getSourceMapRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + export function getTokenSourceMapRange(node: Node, token: SyntaxKind) { + const emitNode = node.emitNode; + const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } /** * Transforms an array of SourceFiles by passing them through each transformer. @@ -203,18 +283,10 @@ namespace ts { * @param transforms An array of Transformers. */ export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult { - const transformId = nextTransformId; - nextTransformId++; - - const tokenSourceMapRanges = createMap(); const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = []; const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); - const parseTreeNodesWithAnnotations: Node[] = []; - let lastTokenSourceMapRangeNode: Node; - let lastTokenSourceMapRangeToken: SyntaxKind; - let lastTokenSourceMapRange: TextRange; let lexicalEnvironmentStackOffset = 0; let hoistedVariableDeclarations: VariableDeclaration[]; let hoistedFunctionDeclarations: FunctionDeclaration[]; @@ -226,14 +298,6 @@ namespace ts { getCompilerOptions: () => host.getCompilerOptions(), getEmitResolver: () => resolver, getEmitHost: () => host, - getNodeEmitFlags, - setNodeEmitFlags, - getSourceMapRange, - setSourceMapRange, - getTokenSourceMapRange, - setTokenSourceMapRange, - getCommentRange, - setCommentRange, hoistVariableDeclaration, hoistFunctionDeclaration, startLexicalEnvironment, @@ -257,7 +321,6 @@ namespace ts { return { getSourceFiles: () => transformed, - getTokenSourceMapRange, isSubstitutionEnabled, isEmitNotificationEnabled, onSubstituteNode: context.onSubstituteNode, @@ -269,16 +332,9 @@ namespace ts { // from these nodes to ensure we do not hold onto entire subtrees just for position // information. We also need to reset these nodes to a pre-transformation state // for incremental parsing scenarios so that we do not impact later emit. - for (const node of parseTreeNodesWithAnnotations) { - if (node.transformId === transformId) { - node.transformId = 0; - node.emitFlags = 0; - node.commentRange = undefined; - node.sourceMapRange = undefined; - } + for (const sourceFile of sourceFiles) { + disposeEmitNodes(sourceFile); } - - parseTreeNodesWithAnnotations.length = 0; } }; @@ -333,7 +389,7 @@ namespace ts { */ function isEmitNotificationEnabled(node: Node) { return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0 - || (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0; + || (getEmitFlags(node) & EmitFlags.AdviseOnEmitNode) !== 0; } /** @@ -346,143 +402,6 @@ namespace ts { emit(node); } - /** - * Associates a node with the current transformation, initializing - * various transient transformation properties. - * - * @param node The node. - */ - function beforeSetAnnotation(node: Node) { - if ((node.flags & NodeFlags.Synthesized) === 0 && node.transformId !== transformId) { - // To avoid holding onto transformation artifacts, we keep track of any - // parse tree node we are annotating. This allows us to clean them up after - // all transformations have completed. - parseTreeNodesWithAnnotations.push(node); - node.transformId = transformId; - } - } - - /** - * Gets flags that control emit behavior of a node. - * - * If the node does not have its own NodeEmitFlags set, the node emit flags of its - * original pointer are used. - * - * @param node The node. - */ - function getNodeEmitFlags(node: Node) { - return node.emitFlags; - } - - /** - * Sets flags that control emit behavior of a node. - * - * @param node The node. - * @param emitFlags The NodeEmitFlags for the node. - */ - function setNodeEmitFlags(node: T, emitFlags: NodeEmitFlags) { - beforeSetAnnotation(node); - node.emitFlags = emitFlags; - return node; - } - - /** - * Gets a custom text range to use when emitting source maps. - * - * If a node does not have its own custom source map text range, the custom source map - * text range of its original pointer is used. - * - * @param node The node. - */ - function getSourceMapRange(node: Node) { - return node.sourceMapRange || node; - } - - /** - * Sets a custom text range to use when emitting source maps. - * - * @param node The node. - * @param range The text range. - */ - function setSourceMapRange(node: T, range: TextRange) { - beforeSetAnnotation(node); - node.sourceMapRange = range; - return node; - } - - /** - * Gets the TextRange to use for source maps for a token of a node. - * - * If a node does not have its own custom source map text range for a token, the custom - * source map text range for the token of its original pointer is used. - * - * @param node The node. - * @param token The token. - */ - function getTokenSourceMapRange(node: Node, token: SyntaxKind) { - // As a performance optimization, use the cached value of the most recent node. - // This helps for cases where this function is called repeatedly for the same node. - if (lastTokenSourceMapRangeNode === node && lastTokenSourceMapRangeToken === token) { - return lastTokenSourceMapRange; - } - - // Get the custom token source map range for a node or from one of its original nodes. - // Custom token ranges are not stored on the node to avoid the GC burden. - let range: TextRange; - let current = node; - while (current) { - range = current.id ? tokenSourceMapRanges[current.id + "-" + token] : undefined; - if (range !== undefined) { - break; - } - - current = current.original; - } - - // Cache the most recently requested value. - lastTokenSourceMapRangeNode = node; - lastTokenSourceMapRangeToken = token; - lastTokenSourceMapRange = range; - return range; - } - - /** - * Sets the TextRange to use for source maps for a token of a node. - * - * @param node The node. - * @param token The token. - * @param range The text range. - */ - function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { - // Cache the most recently requested value. - lastTokenSourceMapRangeNode = node; - lastTokenSourceMapRangeToken = token; - lastTokenSourceMapRange = range; - tokenSourceMapRanges[getNodeId(node) + "-" + token] = range; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - * - * If a node does not have its own custom source map text range, the custom source map - * text range of its original pointer is used. - * - * @param node The node. - */ - function getCommentRange(node: Node) { - return node.commentRange || node; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - function setCommentRange(node: T, range: TextRange) { - beforeSetAnnotation(node); - node.commentRange = range; - return node; - } - /** * Records a hoisted variable declaration for the provided name within a lexical environment. */ @@ -563,70 +482,4 @@ namespace ts { return statements; } } - - /** - * High-order function, creates a function that executes a function composition. - * For example, `chain(a, b)` is the equivalent of `x => ((a', b') => y => b'(a'(y)))(a(x), b(x))` - * - * @param args The functions to chain. - */ - function chain(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U; - function chain(a: (t: T) => (u: U) => U, b: (t: T) => (u: U) => U, c: (t: T) => (u: U) => U, d: (t: T) => (u: U) => U, e: (t: T) => (u: U) => U): (t: T) => (u: U) => U { - if (e) { - const args: ((t: T) => (u: U) => U)[] = []; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - - return t => compose(...map(args, f => f(t))); - } - else if (d) { - return t => compose(a(t), b(t), c(t), d(t)); - } - else if (c) { - return t => compose(a(t), b(t), c(t)); - } - else if (b) { - return t => compose(a(t), b(t)); - } - else if (a) { - return t => compose(a(t)); - } - else { - return t => u => u; - } - } - - /** - * High-order function, composes functions. Note that functions are composed inside-out; - * for example, `compose(a, b)` is the equivalent of `x => b(a(x))`. - * - * @param args The functions to compose. - */ - function compose(...args: ((t: T) => T)[]): (t: T) => T; - function compose(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T { - if (e) { - const args: ((t: T) => T)[] = []; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - - return t => reduceLeft<(t: T) => T, T>(args, (u, f) => f(u), t); - } - else if (d) { - return t => d(c(b(a(t)))); - } - else if (c) { - return t => c(b(a(t))); - } - else if (b) { - return t => b(a(t)); - } - else if (a) { - return t => a(t); - } - else { - return t => t; - } - } } \ No newline at end of file diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index c6079ee1378..ac433647f55 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -66,7 +66,7 @@ namespace ts { // NOTE: this completely disables source maps, but aligns with the behavior of // `emitAssignment` in the old emitter. - context.setNodeEmitFlags(expression, NodeEmitFlags.NoNestedSourceMaps); + setEmitFlags(expression, EmitFlags.NoNestedSourceMaps); aggregateTransformFlags(expression); expressions.push(expression); @@ -102,7 +102,7 @@ namespace ts { // NOTE: this completely disables source maps, but aligns with the behavior of // `emitAssignment` in the old emitter. - context.setNodeEmitFlags(declaration, NodeEmitFlags.NoNestedSourceMaps); + setEmitFlags(declaration, EmitFlags.NoNestedSourceMaps); aggregateTransformFlags(declaration); declarations.push(declaration); @@ -139,7 +139,7 @@ namespace ts { // NOTE: this completely disables source maps, but aligns with the behavior of // `emitAssignment` in the old emitter. - context.setNodeEmitFlags(declaration, NodeEmitFlags.NoNestedSourceMaps); + setEmitFlags(declaration, EmitFlags.NoNestedSourceMaps); declarations.push(declaration); aggregateTransformFlags(declaration); @@ -192,7 +192,7 @@ namespace ts { // NOTE: this completely disables source maps, but aligns with the behavior of // `emitAssignment` in the old emitter. - context.setNodeEmitFlags(expression, NodeEmitFlags.NoNestedSourceMaps); + setEmitFlags(expression, EmitFlags.NoNestedSourceMaps); pendingAssignments.push(expression); return expression; @@ -252,8 +252,8 @@ namespace ts { } else { const name = getMutableClone(target); - context.setSourceMapRange(name, target); - context.setCommentRange(name, target); + setSourceMapRange(name, target); + setCommentRange(name, target); emitAssignment(name, value, location, /*original*/ undefined); } } diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 51a6a088fb7..eda0d03c704 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -144,13 +144,6 @@ namespace ts { startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration, - getNodeEmitFlags, - setNodeEmitFlags, - getCommentRange, - setCommentRange, - getSourceMapRange, - setSourceMapRange, - setTokenSourceMapRange, } = context; const resolver = context.getEmitResolver(); @@ -190,6 +183,10 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + currentSourceFile = node; currentText = node.text; return visitNode(node, visitor, isSourceFile); @@ -427,7 +424,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.FunctionDeclaration: containingNonArrowFunction = currentParent; - if (!(containingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody)) { + if (!(getEmitFlags(containingNonArrowFunction) & EmitFlags.AsyncFunctionBody)) { superScopeContainer = containingNonArrowFunction; } break; @@ -669,19 +666,19 @@ namespace ts { // To preserve the behavior of the old emitter, we explicitly indent // the body of the function here if it was requested in an earlier // transformation. - if (getNodeEmitFlags(node) & NodeEmitFlags.Indented) { - setNodeEmitFlags(classFunction, NodeEmitFlags.Indented); + if (getEmitFlags(node) & EmitFlags.Indented) { + setEmitFlags(classFunction, EmitFlags.Indented); } // "inner" and "outer" below are added purely to preserve source map locations from // the old emitter const inner = createPartiallyEmittedExpression(classFunction); inner.end = node.end; - setNodeEmitFlags(inner, NodeEmitFlags.NoComments); + setEmitFlags(inner, EmitFlags.NoComments); const outer = createPartiallyEmittedExpression(inner); outer.end = skipTrivia(currentText, node.pos); - setNodeEmitFlags(outer, NodeEmitFlags.NoComments); + setEmitFlags(outer, EmitFlags.NoComments); return createParen( createCall( @@ -715,17 +712,17 @@ namespace ts { // emit with the original emitter. const outer = createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; - setNodeEmitFlags(outer, NodeEmitFlags.NoComments); + setEmitFlags(outer, EmitFlags.NoComments); const statement = createReturn(outer); statement.pos = closingBraceLocation.pos; - setNodeEmitFlags(statement, NodeEmitFlags.NoComments | NodeEmitFlags.NoTokenSourceMaps); + setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps); statements.push(statement); addRange(statements, endLexicalEnvironment()); const block = createBlock(createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true); - setNodeEmitFlags(block, NodeEmitFlags.NoComments); + setEmitFlags(block, EmitFlags.NoComments); return block; } @@ -828,7 +825,7 @@ namespace ts { ); if (!constructor) { - setNodeEmitFlags(block, NodeEmitFlags.NoComments); + setEmitFlags(block, EmitFlags.NoComments); } return block; @@ -965,27 +962,27 @@ namespace ts { // of an initializer, we must emit that expression to preserve side effects. if (name.elements.length > 0) { statements.push( - setNodeEmitFlags( + setEmitFlags( createVariableStatement( /*modifiers*/ undefined, createVariableDeclarationList( flattenParameterDestructuring(context, parameter, temp, visitor) ) ), - NodeEmitFlags.CustomPrologue + EmitFlags.CustomPrologue ) ); } else if (initializer) { statements.push( - setNodeEmitFlags( + setEmitFlags( createStatement( createAssignment( temp, visitNode(initializer, visitor, isExpression) ) ), - NodeEmitFlags.CustomPrologue + EmitFlags.CustomPrologue ) ); } @@ -1006,23 +1003,23 @@ namespace ts { getSynthesizedClone(name), createVoidZero() ), - setNodeEmitFlags( + setEmitFlags( createBlock([ createStatement( createAssignment( - setNodeEmitFlags(getMutableClone(name), NodeEmitFlags.NoSourceMap), - setNodeEmitFlags(initializer, NodeEmitFlags.NoSourceMap | getNodeEmitFlags(initializer)), + setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap), + setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)), /*location*/ parameter ) ) ], /*location*/ parameter), - NodeEmitFlags.SingleLine | NodeEmitFlags.NoTrailingSourceMap | NodeEmitFlags.NoTokenSourceMaps + EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps ), /*elseStatement*/ undefined, /*location*/ parameter ); statement.startsOnNewLine = true; - setNodeEmitFlags(statement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoTrailingSourceMap | NodeEmitFlags.CustomPrologue); + setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue); statements.push(statement); } @@ -1055,7 +1052,7 @@ namespace ts { // `declarationName` is the name of the local declaration for the parameter. const declarationName = getMutableClone(parameter.name); - setNodeEmitFlags(declarationName, NodeEmitFlags.NoSourceMap); + setEmitFlags(declarationName, EmitFlags.NoSourceMap); // `expressionName` is the name of the parameter used in expressions. const expressionName = getSynthesizedClone(parameter.name); @@ -1064,7 +1061,7 @@ namespace ts { // var param = []; statements.push( - setNodeEmitFlags( + setEmitFlags( createVariableStatement( /*modifiers*/ undefined, createVariableDeclarationList([ @@ -1076,7 +1073,7 @@ namespace ts { ]), /*location*/ parameter ), - NodeEmitFlags.CustomPrologue + EmitFlags.CustomPrologue ) ); @@ -1109,7 +1106,7 @@ namespace ts { ]) ); - setNodeEmitFlags(forStatement, NodeEmitFlags.CustomPrologue); + setEmitFlags(forStatement, EmitFlags.CustomPrologue); startOnNewLine(forStatement); statements.push(forStatement); } @@ -1134,7 +1131,7 @@ namespace ts { ]) ); - setNodeEmitFlags(captureThisStatement, NodeEmitFlags.NoComments | NodeEmitFlags.CustomPrologue); + setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue); setSourceMapRange(captureThisStatement, node); statements.push(captureThisStatement); } @@ -1198,7 +1195,7 @@ namespace ts { const sourceMapRange = getSourceMapRange(member); const func = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined); - setNodeEmitFlags(func, NodeEmitFlags.NoComments); + setEmitFlags(func, EmitFlags.NoComments); setSourceMapRange(func, sourceMapRange); const statement = createStatement( @@ -1219,7 +1216,7 @@ namespace ts { // The location for the statement is used to emit comments only. // No source map should be emitted for this statement to align with the // old emitter. - setNodeEmitFlags(statement, NodeEmitFlags.NoSourceMap); + setEmitFlags(statement, EmitFlags.NoSourceMap); return statement; } @@ -1238,7 +1235,7 @@ namespace ts { // The location for the statement is used to emit source maps only. // No comments should be emitted for this statement to align with the // old emitter. - setNodeEmitFlags(statement, NodeEmitFlags.NoComments); + setEmitFlags(statement, EmitFlags.NoComments); return statement; } @@ -1252,11 +1249,11 @@ namespace ts { // To align with source maps in the old emitter, the receiver and property name // arguments are both mapped contiguously to the accessor name. const target = getMutableClone(receiver); - setNodeEmitFlags(target, NodeEmitFlags.NoComments | NodeEmitFlags.NoTrailingSourceMap); + setEmitFlags(target, EmitFlags.NoComments | EmitFlags.NoTrailingSourceMap); setSourceMapRange(target, firstAccessor.name); const propertyName = createExpressionForPropertyName(visitNode(firstAccessor.name, visitor, isPropertyName)); - setNodeEmitFlags(propertyName, NodeEmitFlags.NoComments | NodeEmitFlags.NoLeadingSourceMap); + setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoLeadingSourceMap); setSourceMapRange(propertyName, firstAccessor.name); const properties: ObjectLiteralElement[] = []; @@ -1312,7 +1309,7 @@ namespace ts { const func = transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined); useCapturedThis = savedUseCapturedThis; - setNodeEmitFlags(func, NodeEmitFlags.CapturesThis); + setEmitFlags(func, EmitFlags.CapturesThis); return func; } @@ -1437,7 +1434,7 @@ namespace ts { const expression = visitNode(body, visitor, isExpression); const returnStatement = createReturn(expression, /*location*/ body); - setNodeEmitFlags(returnStatement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoTrailingSourceMap | NodeEmitFlags.NoTrailingComments); + setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments); statements.push(returnStatement); // To align with the source map emit for the old emitter, we set a custom @@ -1455,7 +1452,7 @@ namespace ts { const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine); if (!multiLine && singleLine) { - setNodeEmitFlags(block, NodeEmitFlags.SingleLine); + setEmitFlags(block, EmitFlags.SingleLine); } if (closeBraceLocation) { @@ -1875,7 +1872,7 @@ namespace ts { } // The old emitter does not emit source maps for the expression - setNodeEmitFlags(expression, NodeEmitFlags.NoSourceMap | getNodeEmitFlags(expression)); + setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression)); // The old emitter does not emit source maps for the block. // We add the location to preserve comments. @@ -1884,7 +1881,7 @@ namespace ts { /*location*/ bodyLocation ); - setNodeEmitFlags(body, NodeEmitFlags.NoSourceMap | NodeEmitFlags.NoTokenSourceMaps); + setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps); const forStatement = createFor( createVariableDeclarationList([ @@ -1902,7 +1899,7 @@ namespace ts { ); // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. - setNodeEmitFlags(forStatement, NodeEmitFlags.NoTokenTrailingSourceMaps); + setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps); return forStatement; } @@ -1938,13 +1935,13 @@ namespace ts { const expressions: Expression[] = []; const assignment = createAssignment( temp, - setNodeEmitFlags( + setEmitFlags( createObjectLiteral( visitNodes(properties, visitor, isObjectLiteralElement, 0, numInitialProperties), /*location*/ undefined, node.multiLine ), - NodeEmitFlags.Indented + EmitFlags.Indented ) ); if (node.multiLine) { @@ -2067,16 +2064,16 @@ namespace ts { const isAsyncBlockContainingAwait = containingNonArrowFunction - && (containingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody) !== 0 + && (getEmitFlags(containingNonArrowFunction) & EmitFlags.AsyncFunctionBody) !== 0 && (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; - let loopBodyFlags: NodeEmitFlags = 0; + let loopBodyFlags: EmitFlags = 0; if (currentState.containsLexicalThis) { - loopBodyFlags |= NodeEmitFlags.CapturesThis; + loopBodyFlags |= EmitFlags.CapturesThis; } if (isAsyncBlockContainingAwait) { - loopBodyFlags |= NodeEmitFlags.AsyncFunctionBody; + loopBodyFlags |= EmitFlags.AsyncFunctionBody; } const convertedLoopVariable = @@ -2087,7 +2084,7 @@ namespace ts { createVariableDeclaration( functionName, /*type*/ undefined, - setNodeEmitFlags( + setEmitFlags( createFunctionExpression( isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined, /*name*/ undefined, @@ -2480,7 +2477,7 @@ namespace ts { // Methods with computed property names are handled in visitObjectLiteralExpression. Debug.assert(!isComputedPropertyName(node.name)); const functionExpression = transformFunctionLikeToExpression(node, /*location*/ moveRangePos(node, -1), /*name*/ undefined); - setNodeEmitFlags(functionExpression, NodeEmitFlags.NoLeadingComments | getNodeEmitFlags(functionExpression)); + setEmitFlags(functionExpression, EmitFlags.NoLeadingComments | getEmitFlags(functionExpression)); return createPropertyAssignment( node.name, functionExpression, @@ -2861,7 +2858,7 @@ namespace ts { if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis && isFunctionLike(node)) { // If we are tracking a captured `this`, push a bit that indicates whether the // containing function is an arrow function. - useCapturedThis = (getNodeEmitFlags(node) & NodeEmitFlags.CapturesThis) !== 0; + useCapturedThis = (getEmitFlags(node) & EmitFlags.CapturesThis) !== 0; } previousOnEmitNode(node, emit); @@ -3012,7 +3009,7 @@ namespace ts { * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ function getLocalName(node: ClassDeclaration | ClassExpression | FunctionDeclaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getDeclarationName(node, allowComments, allowSourceMaps, NodeEmitFlags.LocalName); + return getDeclarationName(node, allowComments, allowSourceMaps, EmitFlags.LocalName); } /** @@ -3021,18 +3018,18 @@ namespace ts { * @param node The declaration. * @param allowComments Allow comments for the name. */ - function getDeclarationName(node: DeclarationStatement | ClassExpression, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: NodeEmitFlags) { + function getDeclarationName(node: DeclarationStatement | ClassExpression, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) { if (node.name && !isGeneratedIdentifier(node.name)) { const name = getMutableClone(node.name); - emitFlags |= getNodeEmitFlags(node.name); + emitFlags |= getEmitFlags(node.name); if (!allowSourceMaps) { - emitFlags |= NodeEmitFlags.NoSourceMap; + emitFlags |= EmitFlags.NoSourceMap; } if (!allowComments) { - emitFlags |= NodeEmitFlags.NoComments; + emitFlags |= EmitFlags.NoComments; } if (emitFlags) { - setNodeEmitFlags(name, emitFlags); + setEmitFlags(name, emitFlags); } return name; } diff --git a/src/compiler/transformers/es7.ts b/src/compiler/transformers/es7.ts index 5d848bc608b..4d5e96134c4 100644 --- a/src/compiler/transformers/es7.ts +++ b/src/compiler/transformers/es7.ts @@ -9,6 +9,10 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + return visitEachChild(node, visitor, context); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index d1e2b6033a6..d6a30a81d61 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -231,9 +231,6 @@ namespace ts { endLexicalEnvironment, hoistFunctionDeclaration, hoistVariableDeclaration, - setSourceMapRange, - setCommentRange, - setNodeEmitFlags } = context; const compilerOptions = context.getCompilerOptions(); @@ -294,6 +291,10 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + if (node.transformFlags & TransformFlags.ContainsGenerator) { currentSourceFile = node; node = visitEachChild(node, visitor, context); @@ -444,7 +445,7 @@ namespace ts { */ function visitFunctionDeclaration(node: FunctionDeclaration): Statement { // Currently, we only support generators that were originally async functions. - if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) { + if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { node = setOriginalNode( createFunctionDeclaration( /*decorators*/ undefined, @@ -492,7 +493,7 @@ namespace ts { */ function visitFunctionExpression(node: FunctionExpression): Expression { // Currently, we only support generators that were originally async functions. - if (node.asteriskToken && node.emitFlags & NodeEmitFlags.AsyncFunctionBody) { + if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { node = setOriginalNode( createFunctionExpression( /*asteriskToken*/ undefined, @@ -2580,7 +2581,7 @@ namespace ts { /*typeArguments*/ undefined, [ createThis(), - setNodeEmitFlags( + setEmitFlags( createFunctionExpression( /*asteriskToken*/ undefined, /*name*/ undefined, @@ -2593,7 +2594,7 @@ namespace ts { /*multiLine*/ buildResult.length > 0 ) ), - NodeEmitFlags.ReuseTempVariableScope + EmitFlags.ReuseTempVariableScope ) ] ); diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 9e6aa507cce..95a4016bb0a 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -16,6 +16,10 @@ namespace ts { * @param node A SourceFile node. */ function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + currentSourceFile = node; node = visitEachChild(node, visitor, context); currentSourceFile = undefined; diff --git a/src/compiler/transformers/module/es6.ts b/src/compiler/transformers/module/es6.ts index 2716165f2d3..09a2890727c 100644 --- a/src/compiler/transformers/module/es6.ts +++ b/src/compiler/transformers/module/es6.ts @@ -12,6 +12,10 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + if (isExternalModule(node) || compilerOptions.isolatedModules) { currentSourceFile = node; return visitEachChild(node, visitor, context); diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 9abd91b47c8..286ef967288 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -15,9 +15,6 @@ namespace ts { startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration, - setNodeEmitFlags, - getNodeEmitFlags, - setSourceMapRange, } = context; const compilerOptions = context.getCompilerOptions(); @@ -54,6 +51,10 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + if (isExternalModule(node) || compilerOptions.isolatedModules) { currentSourceFile = node; @@ -92,7 +93,7 @@ namespace ts { const updated = updateSourceFile(node, statements); if (hasExportStarsToExportValues) { - setNodeEmitFlags(updated, NodeEmitFlags.EmitExportStar | getNodeEmitFlags(node)); + setEmitFlags(updated, EmitFlags.EmitExportStar | getEmitFlags(node)); } return updated; @@ -116,7 +117,7 @@ namespace ts { */ function transformUMDModule(node: SourceFile) { const define = createIdentifier("define"); - setNodeEmitFlags(define, NodeEmitFlags.UMDDefine); + setEmitFlags(define, EmitFlags.UMDDefine); return transformAsynchronousModule(node, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false); } @@ -220,7 +221,7 @@ namespace ts { if (hasExportStarsToExportValues) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. - setNodeEmitFlags(body, NodeEmitFlags.EmitExportStar); + setEmitFlags(body, EmitFlags.EmitExportStar); } return body; @@ -234,7 +235,7 @@ namespace ts { /*location*/ exportEquals ); - setNodeEmitFlags(statement, NodeEmitFlags.NoTokenSourceMaps | NodeEmitFlags.NoComments); + setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments); statements.push(statement); } else { @@ -249,7 +250,7 @@ namespace ts { /*location*/ exportEquals ); - setNodeEmitFlags(statement, NodeEmitFlags.NoComments); + setEmitFlags(statement, EmitFlags.NoComments); statements.push(statement); } } @@ -388,7 +389,7 @@ namespace ts { // Set emitFlags on the name of the importEqualsDeclaration // This is so the printer will not substitute the identifier - setNodeEmitFlags(node.name, NodeEmitFlags.NoSubstitution); + setEmitFlags(node.name, EmitFlags.NoSubstitution); const statements: Statement[] = []; if (moduleKind !== ModuleKind.AMD) { if (hasModifier(node, ModifierFlags.Export)) { @@ -598,7 +599,7 @@ namespace ts { } else { statements.push( - createExportStatement(node.name, setNodeEmitFlags(getSynthesizedClone(node.name), NodeEmitFlags.LocalName), /*location*/ node) + createExportStatement(node.name, setEmitFlags(getSynthesizedClone(node.name), EmitFlags.LocalName), /*location*/ node) ); } } @@ -813,7 +814,7 @@ namespace ts { )], /*location*/ node ); - setNodeEmitFlags(transformedStatement, NodeEmitFlags.NoComments); + setEmitFlags(transformedStatement, EmitFlags.NoComments); statements.push(transformedStatement); } @@ -890,7 +891,7 @@ namespace ts { // If the left-hand-side of the binaryExpression is an identifier and its is export through export Specifier if (isIdentifier(left) && isAssignmentOperator(node.operatorToken.kind)) { if (bindingNameExportSpecifiersMap && hasProperty(bindingNameExportSpecifiersMap, left.text)) { - setNodeEmitFlags(node, NodeEmitFlags.NoSubstitution); + setEmitFlags(node, EmitFlags.NoSubstitution); let nestedExportAssignment: BinaryExpression; for (const specifier of bindingNameExportSpecifiersMap[left.text]) { nestedExportAssignment = nestedExportAssignment ? @@ -910,7 +911,7 @@ namespace ts { const operand = node.operand; if (isIdentifier(operand) && bindingNameExportSpecifiersForFileMap) { if (bindingNameExportSpecifiersMap && hasProperty(bindingNameExportSpecifiersMap, operand.text)) { - setNodeEmitFlags(node, NodeEmitFlags.NoSubstitution); + setEmitFlags(node, EmitFlags.NoSubstitution); let transformedUnaryExpression: BinaryExpression; if (node.kind === SyntaxKind.PostfixUnaryExpression) { transformedUnaryExpression = createBinary( @@ -920,7 +921,7 @@ namespace ts { /*location*/ node ); // We have to set no substitution flag here to prevent visit the binary expression and substitute it again as we will preform all necessary substitution in here - setNodeEmitFlags(transformedUnaryExpression, NodeEmitFlags.NoSubstitution); + setEmitFlags(transformedUnaryExpression, EmitFlags.NoSubstitution); } let nestedExportAssignment: BinaryExpression; for (const specifier of bindingNameExportSpecifiersMap[operand.text]) { @@ -935,9 +936,9 @@ namespace ts { } function trySubstituteExportedName(node: Identifier) { - const emitFlags = getNodeEmitFlags(node); - if ((emitFlags & NodeEmitFlags.LocalName) === 0) { - const container = resolver.getReferencedExportContainer(node, (emitFlags & NodeEmitFlags.ExportName) !== 0); + const emitFlags = getEmitFlags(node); + if ((emitFlags & EmitFlags.LocalName) === 0) { + const container = resolver.getReferencedExportContainer(node, (emitFlags & EmitFlags.ExportName) !== 0); if (container) { if (container.kind === SyntaxKind.SourceFile) { return createPropertyAccess( @@ -953,7 +954,7 @@ namespace ts { } function trySubstituteImportedName(node: Identifier): Expression { - if ((getNodeEmitFlags(node) & NodeEmitFlags.LocalName) === 0) { + if ((getEmitFlags(node) & EmitFlags.LocalName) === 0) { const declaration = resolver.getReferencedImportDeclaration(node); if (declaration) { if (isImportClause(declaration)) { @@ -1077,7 +1078,7 @@ namespace ts { if (includeNonAmdDependencies && importAliasName) { // Set emitFlags on the name of the classDeclaration // This is so that when printer will not substitute the identifier - setNodeEmitFlags(importAliasName, NodeEmitFlags.NoSubstitution); + setEmitFlags(importAliasName, EmitFlags.NoSubstitution); aliasedModuleNames.push(externalModuleName); importAliasNames.push(createParameter(importAliasName)); } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 7b013e18e7d..2a14f341272 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -10,8 +10,6 @@ namespace ts { } const { - getNodeEmitFlags, - setNodeEmitFlags, startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration, @@ -50,6 +48,10 @@ namespace ts { return transformSourceFile; function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + if (isExternalModule(node) || compilerOptions.isolatedModules) { currentSourceFile = node; currentNode = node; @@ -116,9 +118,9 @@ namespace ts { createParameter(contextObjectForFile) ], /*type*/ undefined, - setNodeEmitFlags( + setEmitFlags( createBlock(statements, /*location*/ undefined, /*multiLine*/ true), - NodeEmitFlags.EmitEmitHelpers + EmitFlags.EmitEmitHelpers ) ); @@ -135,7 +137,7 @@ namespace ts { : [dependencies, body] ) ) - ], /*nodeEmitFlags*/ ~NodeEmitFlags.EmitEmitHelpers & getNodeEmitFlags(node)); + ], /*nodeEmitFlags*/ ~EmitFlags.EmitEmitHelpers & getEmitFlags(node)); } /** @@ -1053,7 +1055,7 @@ namespace ts { } function substituteAssignmentExpression(node: BinaryExpression): Expression { - setNodeEmitFlags(node, NodeEmitFlags.NoSubstitution); + setEmitFlags(node, EmitFlags.NoSubstitution); const left = node.left; switch (left.kind) { @@ -1176,7 +1178,7 @@ namespace ts { const exportDeclaration = resolver.getReferencedExportContainer(operand); if (exportDeclaration) { const expr = createPrefix(node.operator, operand, node); - setNodeEmitFlags(expr, NodeEmitFlags.NoSubstitution); + setEmitFlags(expr, EmitFlags.NoSubstitution); const call = createExportExpression(operand, expr); if (node.kind === SyntaxKind.PrefixUnaryExpression) { return call; @@ -1241,7 +1243,7 @@ namespace ts { ]), m, createBlock([ - setNodeEmitFlags( + setEmitFlags( createIf( condition, createStatement( @@ -1251,7 +1253,7 @@ namespace ts { ) ) ), - NodeEmitFlags.SingleLine + EmitFlags.SingleLine ) ]) ), @@ -1393,10 +1395,10 @@ namespace ts { hoistBindingElement(node, /*isExported*/ false); } - function updateSourceFile(node: SourceFile, statements: Statement[], nodeEmitFlags: NodeEmitFlags) { + function updateSourceFile(node: SourceFile, statements: Statement[], nodeEmitFlags: EmitFlags) { const updated = getMutableClone(node); updated.statements = createNodeArray(statements, node.statements); - setNodeEmitFlags(updated, nodeEmitFlags); + setEmitFlags(updated, nodeEmitFlags); return updated; } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index d41a32d92c7..e1892ff5bf4 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -24,10 +24,6 @@ namespace ts { export function transformTypeScript(context: TransformationContext) { const { - getNodeEmitFlags, - setNodeEmitFlags, - setCommentRange, - setSourceMapRange, startLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration, @@ -85,6 +81,10 @@ namespace ts { * @param node A SourceFile node. */ function transformSourceFile(node: SourceFile) { + if (isDeclarationFile(node)) { + return node; + } + return visitNode(node, visitor, isSourceFile); } @@ -449,7 +449,7 @@ namespace ts { node = visitEachChild(node, visitor, context); } - setNodeEmitFlags(node, NodeEmitFlags.EmitEmitHelpers | node.emitFlags); + setEmitFlags(node, EmitFlags.EmitEmitHelpers | getEmitFlags(node)); return node; } @@ -521,7 +521,7 @@ namespace ts { // To better align with the old emitter, we should not emit a trailing source map // entry if the class has static properties. if (staticProperties.length > 0) { - setNodeEmitFlags(classDeclaration, NodeEmitFlags.NoTrailingSourceMap | getNodeEmitFlags(classDeclaration)); + setEmitFlags(classDeclaration, EmitFlags.NoTrailingSourceMap | getEmitFlags(classDeclaration)); } statements.push(classDeclaration); @@ -776,7 +776,7 @@ namespace ts { // To preserve the behavior of the old emitter, we explicitly indent // the body of a class with static initializers. - setNodeEmitFlags(classExpression, NodeEmitFlags.Indented | getNodeEmitFlags(classExpression)); + setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); expressions.push(startOnNewLine(createAssignment(temp, classExpression))); addRange(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp)); expressions.push(startOnNewLine(temp)); @@ -1009,10 +1009,10 @@ namespace ts { Debug.assert(isIdentifier(node.name)); const name = node.name as Identifier; const propertyName = getMutableClone(name); - setNodeEmitFlags(propertyName, NodeEmitFlags.NoComments | NodeEmitFlags.NoSourceMap); + setEmitFlags(propertyName, EmitFlags.NoComments | EmitFlags.NoSourceMap); const localName = getMutableClone(name); - setNodeEmitFlags(localName, NodeEmitFlags.NoComments); + setEmitFlags(localName, EmitFlags.NoComments); return startOnNewLine( createStatement( @@ -1418,7 +1418,7 @@ namespace ts { moveRangePastDecorators(member) ); - setNodeEmitFlags(helper, NodeEmitFlags.NoComments); + setEmitFlags(helper, EmitFlags.NoComments); return helper; } @@ -1467,7 +1467,7 @@ namespace ts { ); const result = createAssignment(getDeclarationName(node), expression, moveRangePastDecorators(node)); - setNodeEmitFlags(result, NodeEmitFlags.NoComments); + setEmitFlags(result, EmitFlags.NoComments); return result; } // Emit the call to __decorate. Given the class: @@ -1491,7 +1491,7 @@ namespace ts { moveRangePastDecorators(node) ); - setNodeEmitFlags(result, NodeEmitFlags.NoComments); + setEmitFlags(result, EmitFlags.NoComments); return result; } } @@ -1521,7 +1521,7 @@ namespace ts { transformDecorator(decorator), parameterOffset, /*location*/ decorator.expression); - setNodeEmitFlags(helper, NodeEmitFlags.NoComments); + setEmitFlags(helper, EmitFlags.NoComments); expressions.push(helper); } } @@ -2324,11 +2324,11 @@ namespace ts { if (languageVersion >= ScriptTarget.ES6) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) { enableSubstitutionForAsyncMethodsWithSuper(); - setNodeEmitFlags(block, NodeEmitFlags.EmitAdvancedSuperHelper); + setEmitFlags(block, EmitFlags.EmitAdvancedSuperHelper); } else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) { enableSubstitutionForAsyncMethodsWithSuper(); - setNodeEmitFlags(block, NodeEmitFlags.EmitSuperHelper); + setEmitFlags(block, EmitFlags.EmitSuperHelper); } } @@ -2375,7 +2375,7 @@ namespace ts { setOriginalNode(parameter, node); setCommentRange(parameter, node); setSourceMapRange(parameter, moveRangePastModifiers(node)); - setNodeEmitFlags(parameter.name, NodeEmitFlags.NoTrailingSourceMap); + setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap); return parameter; } @@ -2534,7 +2534,7 @@ namespace ts { // We request to be advised when the printer is about to print this node. This allows // us to set up the correct state for later substitutions. - let emitFlags = NodeEmitFlags.AdviseOnEmitNode; + let emitFlags = EmitFlags.AdviseOnEmitNode; // If needed, we should emit a variable declaration for the enum. If we emit // a leading variable declaration, we should not emit leading comments for the @@ -2544,7 +2544,7 @@ namespace ts { // We should still emit the comments if we are emitting a system module. if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= NodeEmitFlags.NoLeadingComments; + emitFlags |= EmitFlags.NoLeadingComments; } } @@ -2584,7 +2584,7 @@ namespace ts { ); setOriginalNode(enumStatement, node); - setNodeEmitFlags(enumStatement, emitFlags); + setEmitFlags(enumStatement, emitFlags); statements.push(enumStatement); if (isNamespaceExport(node)) { @@ -2736,7 +2736,7 @@ namespace ts { // })(m1 || (m1 = {})); // trailing comment module // setCommentRange(statement, node); - setNodeEmitFlags(statement, NodeEmitFlags.NoTrailingComments); + setEmitFlags(statement, EmitFlags.NoTrailingComments); statements.push(statement); } @@ -2759,7 +2759,7 @@ namespace ts { // We request to be advised when the printer is about to print this node. This allows // us to set up the correct state for later substitutions. - let emitFlags = NodeEmitFlags.AdviseOnEmitNode; + let emitFlags = EmitFlags.AdviseOnEmitNode; // If needed, we should emit a variable declaration for the module. If we emit // a leading variable declaration, we should not emit leading comments for the @@ -2768,7 +2768,7 @@ namespace ts { addVarForEnumOrModuleDeclaration(statements, node); // We should still emit the comments if we are emitting a system module. if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= NodeEmitFlags.NoLeadingComments; + emitFlags |= EmitFlags.NoLeadingComments; } } @@ -2820,7 +2820,7 @@ namespace ts { ); setOriginalNode(moduleStatement, node); - setNodeEmitFlags(moduleStatement, emitFlags); + setEmitFlags(moduleStatement, emitFlags); statements.push(moduleStatement); return statements; } @@ -2895,7 +2895,7 @@ namespace ts { // })(hello || (hello = {})); // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. if (body.kind !== SyntaxKind.ModuleBlock) { - setNodeEmitFlags(block, block.emitFlags | NodeEmitFlags.NoComments); + setEmitFlags(block, getEmitFlags(block) | EmitFlags.NoComments); } return block; } @@ -2936,7 +2936,7 @@ namespace ts { } const moduleReference = createExpressionFromEntityName(node.moduleReference); - setNodeEmitFlags(moduleReference, NodeEmitFlags.NoComments | NodeEmitFlags.NoNestedComments); + setEmitFlags(moduleReference, EmitFlags.NoComments | EmitFlags.NoNestedComments); if (isNamedExternalModuleExport(node) || !isNamespaceExport(node)) { // export var ${name} = ${moduleReference}; @@ -3048,15 +3048,15 @@ namespace ts { function getNamespaceMemberName(name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): Expression { const qualifiedName = createPropertyAccess(currentNamespaceContainerName, getSynthesizedClone(name), /*location*/ name); - let emitFlags: NodeEmitFlags; + let emitFlags: EmitFlags; if (!allowComments) { - emitFlags |= NodeEmitFlags.NoComments; + emitFlags |= EmitFlags.NoComments; } if (!allowSourceMaps) { - emitFlags |= NodeEmitFlags.NoSourceMap; + emitFlags |= EmitFlags.NoSourceMap; } if (emitFlags) { - setNodeEmitFlags(qualifiedName, emitFlags); + setEmitFlags(qualifiedName, emitFlags); } return qualifiedName; } @@ -3093,7 +3093,7 @@ namespace ts { * @param allowComments A value indicating whether comments may be emitted for the name. */ function getLocalName(node: DeclarationStatement | ClassExpression, noSourceMaps?: boolean, allowComments?: boolean) { - return getDeclarationName(node, allowComments, !noSourceMaps, NodeEmitFlags.LocalName); + return getDeclarationName(node, allowComments, !noSourceMaps, EmitFlags.LocalName); } /** @@ -3111,7 +3111,7 @@ namespace ts { return getNamespaceMemberName(getDeclarationName(node), allowComments, !noSourceMaps); } - return getDeclarationName(node, allowComments, !noSourceMaps, NodeEmitFlags.ExportName); + return getDeclarationName(node, allowComments, !noSourceMaps, EmitFlags.ExportName); } /** @@ -3122,20 +3122,20 @@ namespace ts { * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. * @param emitFlags Additional NodeEmitFlags to specify for the name. */ - function getDeclarationName(node: DeclarationStatement | ClassExpression, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: NodeEmitFlags) { + function getDeclarationName(node: DeclarationStatement | ClassExpression, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) { if (node.name) { const name = getMutableClone(node.name); - emitFlags |= getNodeEmitFlags(node.name); + emitFlags |= getEmitFlags(node.name); if (!allowSourceMaps) { - emitFlags |= NodeEmitFlags.NoSourceMap; + emitFlags |= EmitFlags.NoSourceMap; } if (!allowComments) { - emitFlags |= NodeEmitFlags.NoComments; + emitFlags |= EmitFlags.NoComments; } if (emitFlags) { - setNodeEmitFlags(name, emitFlags); + setEmitFlags(name, emitFlags); } return name; @@ -3342,7 +3342,7 @@ namespace ts { function trySubstituteNamespaceExportedName(node: Identifier): Expression { // If this is explicitly a local name, do not substitute. - if (enabledSubstitutions & applicableSubstitutions && (getNodeEmitFlags(node) & NodeEmitFlags.LocalName) === 0) { + if (enabledSubstitutions & applicableSubstitutions && (getEmitFlags(node) & EmitFlags.LocalName) === 0) { // If we are nested within a namespace declaration, we may need to qualifiy // an identifier that is exported from a merged namespace. const container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b1b672d015b..c18ebdd7200 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -493,10 +493,7 @@ namespace ts { /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) /* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) - /* @internal */ transformId?: number; // Associates transient transformation properties with a specific transformation (initialized by transformation). - /* @internal */ emitFlags?: NodeEmitFlags; // Transient emit flags for a synthesized node (initialized by transformation). - /* @internal */ sourceMapRange?: TextRange; // Transient custom sourcemap range for a synthesized node (initialized by transformation). - /* @internal */ commentRange?: TextRange; // Transient custom comment range for a synthesized node (initialized by transformation). + /* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms) } export interface NodeArray extends Array, TextRange { @@ -3153,7 +3150,16 @@ namespace ts { } /* @internal */ - export const enum NodeEmitFlags { + export interface EmitNode { + flags?: EmitFlags; + commentRange?: TextRange; + sourceMapRange?: TextRange; + tokenSourceMapRanges?: Map; + annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup. + } + + /* @internal */ + export const enum EmitFlags { EmitEmitHelpers = 1 << 0, // Any emit helpers should be written to this node. EmitExportStar = 1 << 1, // The export * helper should be written to this node. EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.