mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 04:17:34 -06:00
Merge pull request #11165 from Microsoft/emitNode
Transformation API Cleanup
This commit is contained in:
commit
edd8eb8733
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitNodeWithComments(node: Node, emitCallback: (node: Node) => void): void;
|
||||
emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
|
||||
emitTrailingCommentsOfPosition(pos: number): void;
|
||||
}
|
||||
@ -34,22 +34,24 @@ namespace ts {
|
||||
emitTrailingCommentsOfPosition,
|
||||
};
|
||||
|
||||
function emitNodeWithComments(node: Node, emitCallback: (node: Node) => void) {
|
||||
function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
if (disabled) {
|
||||
emitCallback(node);
|
||||
emitCallback(emitContext, node);
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
disableCommentsAndEmit(node, emitCallback);
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -58,8 +60,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,11 +92,13 @@ namespace ts {
|
||||
performance.measure("commentTime", "preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
disableCommentsAndEmit(node, emitCallback);
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
@ -125,9 +129,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,8 +141,10 @@ namespace ts {
|
||||
performance.measure("commentTime", "preEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
disableCommentsAndEmit(node, emitCallback);
|
||||
if (emitFlags & EmitFlags.NoNestedComments && !disabled) {
|
||||
disabled = true;
|
||||
emitCallback(node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
@ -284,17 +290,6 @@ namespace ts {
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
function disableCommentsAndEmit(node: Node, emitCallback: (node: Node) => void): void {
|
||||
if (disabled) {
|
||||
emitCallback(node);
|
||||
}
|
||||
else {
|
||||
disabled = true;
|
||||
emitCallback(node);
|
||||
disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function hasDetachedComments(pos: number) {
|
||||
return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos;
|
||||
}
|
||||
|
||||
@ -840,6 +840,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<T, U>(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U;
|
||||
export function chain<T, U>(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<T>(...args: ((t: T) => T)[]): (t: T) => T;
|
||||
export function compose<T>(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;
|
||||
|
||||
@ -1778,7 +1844,6 @@ namespace ts {
|
||||
this.transformFlags = TransformFlags.None;
|
||||
this.parent = undefined;
|
||||
this.original = undefined;
|
||||
this.transformId = 0;
|
||||
}
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
|
||||
@ -206,10 +206,8 @@ const _super = (function (geti, seti) {
|
||||
|
||||
const sourceMap = createSourceMapWriter(host, writer);
|
||||
const {
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitTokenStart,
|
||||
emitTokenEnd
|
||||
emitNodeWithSourceMap,
|
||||
emitTokenWithSourceMap
|
||||
} = sourceMap;
|
||||
|
||||
const comments = createCommentWriter(host, writer, sourceMap);
|
||||
@ -234,36 +232,27 @@ const _super = (function (geti, seti) {
|
||||
let isOwnFileEmit: boolean;
|
||||
let emitSkipped = false;
|
||||
|
||||
performance.mark("beforeTransform");
|
||||
const sourceFiles = getSourceFilesToEmit(host, targetSourceFile);
|
||||
|
||||
// Transform the source files
|
||||
const transformed = transformFiles(
|
||||
resolver,
|
||||
host,
|
||||
getSourceFilesToEmit(host, targetSourceFile),
|
||||
transformers);
|
||||
|
||||
performance.mark("beforeTransform");
|
||||
const {
|
||||
transformed,
|
||||
emitNodeWithSubstitution,
|
||||
emitNodeWithNotification
|
||||
} = transformFiles(resolver, host, sourceFiles, transformers);
|
||||
performance.measure("transformTime", "beforeTransform");
|
||||
|
||||
// Extract helpers from the result
|
||||
const {
|
||||
getTokenSourceMapRange,
|
||||
isSubstitutionEnabled,
|
||||
isEmitNotificationEnabled,
|
||||
onSubstituteNode,
|
||||
onEmitNode
|
||||
} = transformed;
|
||||
|
||||
performance.mark("beforePrint");
|
||||
|
||||
// Emit each output file
|
||||
forEachTransformedEmitFile(host, transformed.getSourceFiles(), emitFile, emitOnlyDtsFiles);
|
||||
|
||||
// Clean up after transformation
|
||||
transformed.dispose();
|
||||
|
||||
performance.mark("beforePrint");
|
||||
forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles);
|
||||
performance.measure("printTime", "beforePrint");
|
||||
|
||||
// Clean up emit nodes on parse tree
|
||||
for (const sourceFile of sourceFiles) {
|
||||
disposeEmitNodes(sourceFile);
|
||||
}
|
||||
|
||||
return {
|
||||
emitSkipped,
|
||||
diagnostics: emitterDiagnostics.getDiagnostics(),
|
||||
@ -358,154 +347,137 @@ const _super = (function (geti, seti) {
|
||||
currentFileIdentifiers = node.identifiers;
|
||||
sourceMap.setSourceFile(node);
|
||||
comments.setSourceFile(node);
|
||||
emitNodeWithNotification(node, emitWorker);
|
||||
pipelineEmitWithNotification(EmitContext.SourceFile, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node.
|
||||
*/
|
||||
function emit(node: Node) {
|
||||
emitNodeWithNotification(node, emitWithComments);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emits a node with comments.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from emit.
|
||||
*/
|
||||
function emitWithComments(node: Node) {
|
||||
emitNodeWithComments(node, emitWithSourceMap);
|
||||
pipelineEmitWithNotification(EmitContext.Unspecified, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with source maps.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from emitWithComments.
|
||||
* Emits an IdentifierName.
|
||||
*/
|
||||
function emitWithSourceMap(node: Node) {
|
||||
emitNodeWithSourceMap(node, emitWorker);
|
||||
}
|
||||
|
||||
function emitIdentifierName(node: Identifier) {
|
||||
if (node) {
|
||||
emitNodeWithNotification(node, emitIdentifierNameWithComments);
|
||||
}
|
||||
}
|
||||
|
||||
function emitIdentifierNameWithComments(node: Identifier) {
|
||||
emitNodeWithComments(node, emitWorker);
|
||||
pipelineEmitWithNotification(EmitContext.IdentifierName, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression node.
|
||||
*/
|
||||
function emitExpression(node: Expression) {
|
||||
emitNodeWithNotification(node, emitExpressionWithComments);
|
||||
pipelineEmitWithNotification(EmitContext.Expression, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression with comments.
|
||||
* Emits a node with possible notification.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emitExpression pipeline
|
||||
* and should only be called indirectly from emitExpression.
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called from printSourceFile, emit, emitExpression, or
|
||||
* emitIdentifierName.
|
||||
*/
|
||||
function emitExpressionWithComments(node: Expression) {
|
||||
emitNodeWithComments(node, emitExpressionWithSourceMap);
|
||||
function pipelineEmitWithNotification(emitContext: EmitContext, node: Node) {
|
||||
emitNodeWithNotification(emitContext, node, pipelineEmitWithComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an expression with source maps.
|
||||
* Emits a node with comments.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emitExpression pipeline
|
||||
* and should only be called indirectly from emitExpressionWithComments.
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitWithNotification.
|
||||
*/
|
||||
function emitExpressionWithSourceMap(node: Expression) {
|
||||
emitNodeWithSourceMap(node, emitExpressionWorker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with emit notification if available.
|
||||
*/
|
||||
function emitNodeWithNotification(node: Node, emitCallback: (node: Node) => void) {
|
||||
if (node) {
|
||||
if (isEmitNotificationEnabled(node)) {
|
||||
onEmitNode(node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitNodeWithSourceMap(node: Node, emitCallback: (node: Node) => void) {
|
||||
if (node) {
|
||||
emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
emitCallback(node);
|
||||
emitEnd(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceMapRange(node: Node) {
|
||||
return node.sourceMapRange || node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether to skip leading comment emit for a node.
|
||||
*
|
||||
* We do not emit comments for NotEmittedStatement nodes or any node that has
|
||||
* NodeEmitFlags.NoLeadingComments.
|
||||
*
|
||||
* @param node A Node.
|
||||
*/
|
||||
function shouldSkipLeadingCommentsForNode(node: Node) {
|
||||
return isNotEmittedStatement(node)
|
||||
|| (node.emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether to skip source map emit for the start position of a node.
|
||||
*
|
||||
* We do not emit source maps for NotEmittedStatement nodes or any node that
|
||||
* has NodeEmitFlags.NoLeadingSourceMap.
|
||||
*
|
||||
* @param node A Node.
|
||||
*/
|
||||
function shouldSkipLeadingSourceMapForNode(node: Node) {
|
||||
return isNotEmittedStatement(node)
|
||||
|| (node.emitFlags & NodeEmitFlags.NoLeadingSourceMap) !== 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether to skip source map emit for the end position of a node.
|
||||
*
|
||||
* We do not emit source maps for NotEmittedStatement nodes or any node that
|
||||
* has NodeEmitFlags.NoTrailingSourceMap.
|
||||
*
|
||||
* @param node A Node.
|
||||
*/
|
||||
function shouldSkipTrailingSourceMapForNode(node: Node) {
|
||||
return isNotEmittedStatement(node)
|
||||
|| (node.emitFlags & NodeEmitFlags.NoTrailingSourceMap) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether to skip source map emit for a node and its children.
|
||||
*
|
||||
* We do not emit source maps for a node that has NodeEmitFlags.NoNestedSourceMaps.
|
||||
*/
|
||||
function shouldSkipSourceMapForChildren(node: Node) {
|
||||
return (node.emitFlags & NodeEmitFlags.NoNestedSourceMaps) !== 0;
|
||||
}
|
||||
|
||||
function emitWorker(node: Node): void {
|
||||
if (tryEmitSubstitute(node, emitWorker, /*isExpression*/ false)) {
|
||||
function pipelineEmitWithComments(emitContext: EmitContext, node: Node) {
|
||||
// Do not emit comments for SourceFile
|
||||
if (emitContext === EmitContext.SourceFile) {
|
||||
pipelineEmitWithSourceMap(emitContext, node);
|
||||
return;
|
||||
}
|
||||
|
||||
emitNodeWithComments(emitContext, node, pipelineEmitWithSourceMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node with source maps.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitWithComments.
|
||||
*/
|
||||
function pipelineEmitWithSourceMap(emitContext: EmitContext, node: Node) {
|
||||
// Do not emit source mappings for SourceFile or IdentifierName
|
||||
if (emitContext === EmitContext.SourceFile
|
||||
|| emitContext === EmitContext.IdentifierName) {
|
||||
pipelineEmitWithSubstitution(emitContext, node);
|
||||
return;
|
||||
}
|
||||
|
||||
emitNodeWithSourceMap(emitContext, node, pipelineEmitWithSubstitution);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 pipelineEmitWithSourceMap or
|
||||
* pipelineEmitInUnspecifiedContext (when picking a more specific context).
|
||||
*/
|
||||
function pipelineEmitWithSubstitution(emitContext: EmitContext, node: Node) {
|
||||
emitNodeWithSubstitution(emitContext, node, pipelineEmitForContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitWithSubstitution.
|
||||
*/
|
||||
function pipelineEmitForContext(emitContext: EmitContext, node: Node): void {
|
||||
switch (emitContext) {
|
||||
case EmitContext.SourceFile: return pipelineEmitInSourceFileContext(node);
|
||||
case EmitContext.IdentifierName: return pipelineEmitInIdentifierNameContext(node);
|
||||
case EmitContext.Unspecified: return pipelineEmitInUnspecifiedContext(node);
|
||||
case EmitContext.Expression: return pipelineEmitInExpressionContext(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node in the SourceFile EmitContext.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitForContext.
|
||||
*/
|
||||
function pipelineEmitInSourceFileContext(node: Node): void {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
// Top-level nodes
|
||||
case SyntaxKind.SourceFile:
|
||||
return emitSourceFile(<SourceFile>node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node in the IdentifierName EmitContext.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitForContext.
|
||||
*/
|
||||
function pipelineEmitInIdentifierNameContext(node: Node): void {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
// Identifiers
|
||||
case SyntaxKind.Identifier:
|
||||
return emitIdentifier(<Identifier>node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node in the Unspecified EmitContext.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitForContext.
|
||||
*/
|
||||
function pipelineEmitInUnspecifiedContext(node: Node): void {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
// Pseudo-literals
|
||||
@ -541,7 +513,8 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.GlobalKeyword:
|
||||
return writeTokenNode(node);
|
||||
writeTokenText(kind);
|
||||
return;
|
||||
|
||||
// Parse tree nodes
|
||||
|
||||
@ -746,25 +719,24 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.EnumMember:
|
||||
return emitEnumMember(<EnumMember>node);
|
||||
|
||||
// Top-level nodes
|
||||
case SyntaxKind.SourceFile:
|
||||
return emitSourceFile(<SourceFile>node);
|
||||
|
||||
// JSDoc nodes (ignored)
|
||||
|
||||
// Transformation nodes (ignored)
|
||||
}
|
||||
|
||||
// If the node is an expression, try to emit it as an expression with
|
||||
// substitution.
|
||||
if (isExpression(node)) {
|
||||
return emitExpressionWorker(node);
|
||||
return pipelineEmitWithSubstitution(EmitContext.Expression, node);
|
||||
}
|
||||
}
|
||||
|
||||
function emitExpressionWorker(node: Node) {
|
||||
if (tryEmitSubstitute(node, emitExpressionWorker, /*isExpression*/ true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a node in the Expression EmitContext.
|
||||
*
|
||||
* NOTE: Do not call this method directly. It is part of the emit pipeline
|
||||
* and should only be called indirectly from pipelineEmitForContext.
|
||||
*/
|
||||
function pipelineEmitInExpressionContext(node: Node): void {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
// Literals
|
||||
@ -786,7 +758,8 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.SuperKeyword:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return writeTokenNode(node);
|
||||
writeTokenText(kind);
|
||||
return;
|
||||
|
||||
// Expressions
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
@ -888,7 +861,7 @@ const _super = (function (geti, seti) {
|
||||
//
|
||||
|
||||
function emitIdentifier(node: Identifier) {
|
||||
if (node.emitFlags & NodeEmitFlags.UMDDefine) {
|
||||
if (getEmitFlags(node) & EmitFlags.UMDDefine) {
|
||||
writeLines(umdHelper);
|
||||
}
|
||||
else {
|
||||
@ -1161,7 +1134,7 @@ const _super = (function (geti, seti) {
|
||||
write("{}");
|
||||
}
|
||||
else {
|
||||
const indentedFlag = node.emitFlags & NodeEmitFlags.Indented;
|
||||
const indentedFlag = getEmitFlags(node) & EmitFlags.Indented;
|
||||
if (indentedFlag) {
|
||||
increaseIndent();
|
||||
}
|
||||
@ -1177,24 +1150,22 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 = <Node>{ kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd };
|
||||
indentBeforeDot = needsIndentation(node, node.expression, dotToken);
|
||||
indentAfterDot = needsIndentation(node, dotToken, node.name);
|
||||
}
|
||||
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
|
||||
emitExpression(node.expression);
|
||||
increaseIndentIf(indentBeforeDot);
|
||||
|
||||
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
write(shouldEmitDotDot ? ".." : ".");
|
||||
|
||||
increaseIndentIf(indentAfterDot);
|
||||
emit(node.name);
|
||||
decreaseIndentIf(indentBeforeDot, indentAfterDot);
|
||||
@ -1208,19 +1179,17 @@ const _super = (function (geti, seti) {
|
||||
const text = getLiteralTextOfNode(<LiteralExpression>expression);
|
||||
return text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
|
||||
}
|
||||
else {
|
||||
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
|
||||
// check if constant enum value is integer
|
||||
const constantValue = tryGetConstEnumValue(expression);
|
||||
const constantValue = getConstantValue(expression);
|
||||
// isFinite handles cases when constantValue is undefined
|
||||
return isFinite(constantValue) && Math.floor(constantValue) === constantValue;
|
||||
return isFinite(constantValue)
|
||||
&& Math.floor(constantValue) === constantValue
|
||||
&& compilerOptions.removeComments;
|
||||
}
|
||||
}
|
||||
|
||||
function emitElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitExpression(node.expression);
|
||||
write("[");
|
||||
emitExpression(node.argumentExpression);
|
||||
@ -1426,7 +1395,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 {
|
||||
@ -1630,12 +1599,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);
|
||||
}
|
||||
@ -1679,7 +1648,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;
|
||||
}
|
||||
|
||||
@ -1750,7 +1719,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();
|
||||
}
|
||||
@ -2083,8 +2052,8 @@ const _super = (function (geti, seti) {
|
||||
// "comment1" is not considered to be leading comment for node.initializer
|
||||
// but rather a trailing comment on the previous node.
|
||||
const initializer = node.initializer;
|
||||
if (!shouldSkipLeadingCommentsForNode(initializer)) {
|
||||
const commentRange = initializer.commentRange || initializer;
|
||||
if ((getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) {
|
||||
const commentRange = getCommentRange(initializer);
|
||||
emitTrailingCommentsOfPosition(commentRange.pos);
|
||||
}
|
||||
|
||||
@ -2156,23 +2125,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;
|
||||
}
|
||||
@ -2294,36 +2263,6 @@ 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;
|
||||
}
|
||||
|
||||
function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean {
|
||||
const constantValue = tryGetConstEnumValue(node);
|
||||
if (constantValue !== undefined) {
|
||||
write(String(constantValue));
|
||||
if (!compilerOptions.removeComments) {
|
||||
const propertyName = isPropertyAccessExpression(node)
|
||||
? declarationNameToString(node.name)
|
||||
: getTextOfNode(node.argumentExpression);
|
||||
write(` /* ${propertyName} */`);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function emitEmbeddedStatement(node: Statement) {
|
||||
if (isBlock(node)) {
|
||||
write(" ");
|
||||
@ -2447,7 +2386,7 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
if (shouldEmitInterveningComments) {
|
||||
const commentRange = child.commentRange || child;
|
||||
const commentRange = getCommentRange(child);
|
||||
emitTrailingCommentsOfPosition(commentRange.pos);
|
||||
}
|
||||
else {
|
||||
@ -2503,31 +2442,13 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) {
|
||||
const tokenStartPos = emitTokenStart(token, pos, contextNode, shouldSkipLeadingSourceMapForToken, getTokenSourceMapRange);
|
||||
const tokenEndPos = writeTokenText(token, tokenStartPos);
|
||||
return emitTokenEnd(token, tokenEndPos, contextNode, shouldSkipTrailingSourceMapForToken, getTokenSourceMapRange);
|
||||
}
|
||||
|
||||
function shouldSkipLeadingSourceMapForToken(contextNode: Node) {
|
||||
return (contextNode.emitFlags & NodeEmitFlags.NoTokenLeadingSourceMaps) !== 0;
|
||||
}
|
||||
|
||||
function shouldSkipTrailingSourceMapForToken(contextNode: Node) {
|
||||
return (contextNode.emitFlags & NodeEmitFlags.NoTokenTrailingSourceMaps) !== 0;
|
||||
return emitTokenWithSourceMap(contextNode, token, pos, writeTokenText);
|
||||
}
|
||||
|
||||
function writeTokenText(token: SyntaxKind, pos?: number) {
|
||||
const tokenString = tokenToString(token);
|
||||
write(tokenString);
|
||||
return positionIsSynthesized(pos) ? -1 : pos + tokenString.length;
|
||||
}
|
||||
|
||||
function writeTokenNode(node: Node) {
|
||||
if (node) {
|
||||
emitStart(/*range*/ node, /*contextNode*/ node, shouldSkipLeadingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
writeTokenText(node.kind);
|
||||
emitEnd(/*range*/ node, /*contextNode*/ node, shouldSkipTrailingSourceMapForNode, shouldSkipSourceMapForChildren, getSourceMapRange);
|
||||
}
|
||||
return pos < 0 ? pos : pos + tokenString.length;
|
||||
}
|
||||
|
||||
function increaseIndentIf(value: boolean, valueToWriteWhenNotIndenting?: string) {
|
||||
@ -2692,16 +2613,6 @@ const _super = (function (geti, seti) {
|
||||
return getLiteralText(node, currentSourceFile, languageVersion);
|
||||
}
|
||||
|
||||
function tryGetConstEnumValue(node: Node): number {
|
||||
if (compilerOptions.isolatedModules) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return isPropertyAccessExpression(node) || isElementAccessExpression(node)
|
||||
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function isSingleLineEmptyBlock(block: Block) {
|
||||
return !block.multiLine
|
||||
&& block.statements.length === 0
|
||||
|
||||
@ -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 = <T>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 = <PropertyAccessExpression>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,178 @@ namespace ts {
|
||||
export function setOriginalNode<T extends Node>(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<TextRange>, destRanges: Map<TextRange>) {
|
||||
if (!destRanges) destRanges = createMap<TextRange>();
|
||||
copyProperties(sourceRanges, destRanges);
|
||||
return destRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any EmitNode entries from parse-tree nodes.
|
||||
* @param sourceFile A source file.
|
||||
*/
|
||||
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<T extends Node>(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<T extends Node>(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<T extends Node>(node: T, token: SyntaxKind, range: TextRange) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = createMap<TextRange>());
|
||||
tokenSourceMapRanges[token] = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom text range to use when emitting comments.
|
||||
*/
|
||||
export function setCommentRange<T extends Node>(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];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the constant value to emit for an expression.
|
||||
*/
|
||||
export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression) {
|
||||
const emitNode = node.emitNode;
|
||||
return emitNode && emitNode.constantValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the constant value to emit for an expression.
|
||||
*/
|
||||
export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
emitNode.constantValue = value;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setTextRange<T extends TextRange>(node: T, location: TextRange): T {
|
||||
if (location) {
|
||||
node.pos = location.pos;
|
||||
@ -2692,7 +2856,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get the name of a target module from an import/export declaration as should be written in the emitted output.
|
||||
* The emitted output name can be different from the input if:
|
||||
* 1. The module has a /// <amd-module name="<new name>" />
|
||||
|
||||
@ -18,11 +18,6 @@ namespace ts {
|
||||
*/
|
||||
reset(): void;
|
||||
|
||||
/**
|
||||
* Gets test data for source maps.
|
||||
*/
|
||||
getSourceMapData(): SourceMapData;
|
||||
|
||||
/**
|
||||
* Set the current source file.
|
||||
*
|
||||
@ -41,123 +36,23 @@ namespace ts {
|
||||
emitPos(pos: number): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
* Emits a node with possible leading and trailing source maps.
|
||||
*
|
||||
* If the range's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param emitContext The current emit context
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
emitStart(range: TextRange): void;
|
||||
emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the node's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param ignoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this node.
|
||||
* @param ignoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getTextRangeCallbackCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
emitStart(range: TextRange, contextNode: Node, ignoreNodeCallback: (node: Node) => boolean, ignoreChildrenCallback: (node: Node) => boolean, getTextRangeCallbackCallback: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the range's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
*/
|
||||
emitEnd(range: TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the node's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param ignoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this node.
|
||||
* @param ignoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getTextRangeCallbackCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
emitEnd(range: TextRange, contextNode: Node, ignoreNodeCallback: (node: Node) => boolean, ignoreChildrenCallback: (node: Node) => boolean, getTextRangeCallbackCallback: (node: Node) => TextRange): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
* Emits a token of a node node with possible leading and trailing source maps.
|
||||
*
|
||||
* @param node The node containing the token.
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
* @param tokenStartPos The start pos of the token.
|
||||
* @param emitCallback The callback used to emit the token.
|
||||
*/
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param ignoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this token.
|
||||
* @param getTokenTextRangeCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode: Node, ignoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number): number;
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param ignoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this token.
|
||||
* @param getTokenTextRangeCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode: Node, ignoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
|
||||
/*@deprecated*/ changeEmitSourcePos(): void;
|
||||
/*@deprecated*/ stopOverridingSpan(): void;
|
||||
emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenStartPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number): number;
|
||||
|
||||
/**
|
||||
* Gets the text for the source map.
|
||||
@ -168,44 +63,11 @@ namespace ts {
|
||||
* Gets the SourceMappingURL for the source map.
|
||||
*/
|
||||
getSourceMappingURL(): string;
|
||||
}
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) {
|
||||
if (compilerOptions.extendedDiagnostics) {
|
||||
return createSourceMapWriterWithExtendedDiagnostics(host, writer);
|
||||
}
|
||||
|
||||
return createSourceMapWriterWorker(host, writer);
|
||||
}
|
||||
else {
|
||||
return getNullSourceMapWriter();
|
||||
}
|
||||
}
|
||||
|
||||
let nullSourceMapWriter: SourceMapWriter;
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
|
||||
reset(): void { },
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitPos(pos: number): void { },
|
||||
emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { },
|
||||
emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void { },
|
||||
emitTokenStart(token: SyntaxKind, pos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { return -1; },
|
||||
emitTokenEnd(token: SyntaxKind, end: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number { return -1; },
|
||||
changeEmitSourcePos(): void { },
|
||||
stopOverridingSpan(): void { },
|
||||
getText(): string { return undefined; },
|
||||
getSourceMappingURL(): string { return undefined; }
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
/**
|
||||
* Gets test data for source maps.
|
||||
*/
|
||||
getSourceMapData(): SourceMapData;
|
||||
}
|
||||
|
||||
// Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans
|
||||
@ -217,14 +79,12 @@ namespace ts {
|
||||
sourceIndex: 0
|
||||
};
|
||||
|
||||
function createSourceMapWriterWorker(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentSourceText: string;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
let stopOverridingSpan = false;
|
||||
let modifyLastSourcePos = false;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
let sourceMapSourceIndex: number;
|
||||
@ -236,13 +96,7 @@ namespace ts {
|
||||
|
||||
// Source map data
|
||||
let sourceMapData: SourceMapData;
|
||||
|
||||
// This keeps track of the number of times `disable` has been called without a
|
||||
// corresponding call to `enable`. As long as this value is non-zero, mappings will not
|
||||
// be recorded.
|
||||
// This is primarily used to provide a better experience when debugging binding
|
||||
// patterns and destructuring assignments for simple expressions.
|
||||
let disableDepth: number;
|
||||
let disabled: boolean = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap);
|
||||
|
||||
return {
|
||||
initialize,
|
||||
@ -250,12 +104,8 @@ namespace ts {
|
||||
getSourceMapData: () => sourceMapData,
|
||||
setSourceFile,
|
||||
emitPos,
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitTokenStart,
|
||||
emitTokenEnd,
|
||||
changeEmitSourcePos,
|
||||
stopOverridingSpan: () => stopOverridingSpan = true,
|
||||
emitNodeWithSourceMap,
|
||||
emitTokenWithSourceMap,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
};
|
||||
@ -269,13 +119,16 @@ namespace ts {
|
||||
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
|
||||
*/
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourceMapData) {
|
||||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSourceText = undefined;
|
||||
disableDepth = 0;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
sourceMapSourceIndex = -1;
|
||||
@ -338,6 +191,10 @@ namespace ts {
|
||||
* Reset the SourceMapWriter to an empty state.
|
||||
*/
|
||||
function reset() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
sourceMapDir = undefined;
|
||||
sourceMapSourceIndex = undefined;
|
||||
@ -345,64 +202,6 @@ namespace ts {
|
||||
lastEncodedSourceMapSpan = undefined;
|
||||
lastEncodedNameIndex = undefined;
|
||||
sourceMapData = undefined;
|
||||
disableDepth = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enables the recording of mappings.
|
||||
*/
|
||||
function enable() {
|
||||
if (disableDepth > 0) {
|
||||
disableDepth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the recording of mappings.
|
||||
*/
|
||||
function disable() {
|
||||
disableDepth++;
|
||||
}
|
||||
|
||||
function updateLastEncodedAndRecordedSpans() {
|
||||
if (modifyLastSourcePos) {
|
||||
// Reset the source pos
|
||||
modifyLastSourcePos = false;
|
||||
|
||||
// Change Last recorded Map with last encoded emit line and character
|
||||
lastRecordedSourceMapSpan.emittedLine = lastEncodedSourceMapSpan.emittedLine;
|
||||
lastRecordedSourceMapSpan.emittedColumn = lastEncodedSourceMapSpan.emittedColumn;
|
||||
|
||||
// Pop sourceMapDecodedMappings to remove last entry
|
||||
sourceMapData.sourceMapDecodedMappings.pop();
|
||||
|
||||
// Point the lastEncodedSourceMapSpace to the previous encoded sourceMapSpan
|
||||
// If the list is empty which indicates that we are at the beginning of the file,
|
||||
// we have to reset it to default value (same value when we first initialize sourceMapWriter)
|
||||
lastEncodedSourceMapSpan = sourceMapData.sourceMapDecodedMappings.length ?
|
||||
sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] :
|
||||
defaultLastEncodedSourceMapSpan;
|
||||
|
||||
// TODO: Update lastEncodedNameIndex
|
||||
// Since we dont support this any more, lets not worry about it right now.
|
||||
// When we start supporting nameIndex, we will get back to this
|
||||
|
||||
// Change the encoded source map
|
||||
const sourceMapMappings = sourceMapData.sourceMapMappings;
|
||||
let lenthToSet = sourceMapMappings.length - 1;
|
||||
for (; lenthToSet >= 0; lenthToSet--) {
|
||||
const currentChar = sourceMapMappings.charAt(lenthToSet);
|
||||
if (currentChar === ",") {
|
||||
// Separator for the entry found
|
||||
break;
|
||||
}
|
||||
if (currentChar === ";" && lenthToSet !== 0 && sourceMapMappings.charAt(lenthToSet - 1) !== ";") {
|
||||
// Last line separator found
|
||||
break;
|
||||
}
|
||||
}
|
||||
sourceMapData.sourceMapMappings = sourceMapMappings.substr(0, Math.max(0, lenthToSet));
|
||||
}
|
||||
}
|
||||
|
||||
// Encoding for sourcemap span
|
||||
@ -459,7 +258,7 @@ namespace ts {
|
||||
* @param pos The position.
|
||||
*/
|
||||
function emitPos(pos: number) {
|
||||
if (positionIsSynthesized(pos) || disableDepth > 0) {
|
||||
if (disabled || positionIsSynthesized(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -495,209 +294,89 @@ namespace ts {
|
||||
sourceColumn: sourceLinePos.character,
|
||||
sourceIndex: sourceMapSourceIndex
|
||||
};
|
||||
|
||||
stopOverridingSpan = false;
|
||||
}
|
||||
else if (!stopOverridingSpan) {
|
||||
else {
|
||||
// Take the new pos instead since there is no change in emittedLine and column since last location
|
||||
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
|
||||
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
|
||||
lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
|
||||
}
|
||||
|
||||
updateLastEncodedAndRecordedSpans();
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("afterSourcemap");
|
||||
performance.measure("Source Map", "beforeSourcemap", "afterSourcemap");
|
||||
}
|
||||
}
|
||||
|
||||
function getStartPosPastDecorators(range: TextRange) {
|
||||
const rangeHasDecorators = !!(range as Node).decorators;
|
||||
return skipTrivia(currentSourceText, rangeHasDecorators ? (range as Node).decorators.end : range.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
* Emits a node with possible leading and trailing source maps.
|
||||
*
|
||||
* If the range's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.0
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
function emitStart(range: TextRange): void;
|
||||
/**
|
||||
* Emits a mapping for the start of a range.
|
||||
*
|
||||
* If the node's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param ignoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this node.
|
||||
* @param ignoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getTextRangeCallbackCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
function emitStart(range: TextRange, contextNode: Node, ignoreNodeCallback: (node: Node) => boolean, ignoreChildrenCallback: (node: Node) => boolean, getTextRangeCallback: (node: Node) => TextRange): void;
|
||||
function emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange) {
|
||||
if (contextNode) {
|
||||
if (!ignoreNodeCallback(contextNode)) {
|
||||
range = getTextRangeCallback(contextNode) || range;
|
||||
emitPos(getStartPosPastDecorators(range));
|
||||
}
|
||||
|
||||
if (ignoreChildrenCallback(contextNode)) {
|
||||
disable();
|
||||
}
|
||||
function emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
if (disabled) {
|
||||
return emitCallback(emitContext, node);
|
||||
}
|
||||
else {
|
||||
emitPos(getStartPosPastDecorators(range));
|
||||
|
||||
if (node) {
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const { pos, end } = emitNode && emitNode.sourceMapRange || node;
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoLeadingSourceMap) === 0
|
||||
&& pos >= 0) {
|
||||
emitPos(skipTrivia(currentSourceText, pos));
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoTrailingSourceMap) === 0
|
||||
&& end >= 0) {
|
||||
emitPos(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the range's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
*/
|
||||
function emitEnd(range: TextRange): void;
|
||||
/**
|
||||
* Emits a mapping for the end of a range.
|
||||
*
|
||||
* If the node's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param range The range to emit.
|
||||
* @param contextNode The node for the current range.
|
||||
* @param ignoreNodeCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this node.
|
||||
* @param ignoreChildrenCallback A callback used to determine whether to skip source
|
||||
* map emit for all children of this node.
|
||||
* @param getTextRangeCallbackCallback A callback used to get a custom source map
|
||||
* range for this node.
|
||||
*/
|
||||
function emitEnd(range: TextRange, contextNode: Node, ignoreNodeCallback: (node: Node) => boolean, ignoreChildrenCallback: (node: Node) => boolean, getTextRangeCallback: (node: Node) => TextRange): void;
|
||||
function emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange) {
|
||||
if (contextNode) {
|
||||
if (ignoreChildrenCallback(contextNode)) {
|
||||
enable();
|
||||
}
|
||||
|
||||
if (!ignoreNodeCallback(contextNode)) {
|
||||
range = getTextRangeCallback(contextNode) || range;
|
||||
emitPos(range.end);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitPos(range.end);
|
||||
}
|
||||
|
||||
stopOverridingSpan = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
* Emits a token of a node with possible leading and trailing source maps.
|
||||
*
|
||||
* @param node The node containing the token.
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
* @param tokenStartPos The start pos of the token.
|
||||
* @param emitCallback The callback used to emit the token.
|
||||
*/
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number): number;
|
||||
/**
|
||||
* Emits a mapping for the start position of a token.
|
||||
*
|
||||
* If the token's start position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created. Any trivia at the start position in the original source will be
|
||||
* skipped.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenStartPos The start position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param ignoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the start position of this token.
|
||||
* @param getTokenTextRangeCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The start position of the token, following any trivia.
|
||||
*/
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode: Node, ignoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
function emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
if (contextNode) {
|
||||
if (ignoreTokenCallback(contextNode, token)) {
|
||||
return skipTrivia(currentSourceText, tokenStartPos);
|
||||
}
|
||||
|
||||
const range = getTokenTextRangeCallback(contextNode, token);
|
||||
if (range) {
|
||||
tokenStartPos = range.pos;
|
||||
}
|
||||
function emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number) {
|
||||
if (disabled) {
|
||||
return emitCallback(token, tokenPos);
|
||||
}
|
||||
|
||||
tokenStartPos = skipTrivia(currentSourceText, tokenStartPos);
|
||||
emitPos(tokenStartPos);
|
||||
return tokenStartPos;
|
||||
}
|
||||
const emitNode = node && node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token];
|
||||
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number): number;
|
||||
/**
|
||||
* Emits a mapping for the end position of a token.
|
||||
*
|
||||
* If the token's end position is synthetic (undefined or a negative value), no mapping
|
||||
* will be created.
|
||||
*
|
||||
* @param token The token to emit.
|
||||
* @param tokenEndPos The end position of the token.
|
||||
* @param contextNode The node containing this token.
|
||||
* @param ignoreTokenCallback A callback used to determine whether to skip source map
|
||||
* emit for the end position of this token.
|
||||
* @param getTokenTextRangeCallback A callback used to get a custom source
|
||||
* map range for this node.
|
||||
* @returns The end position of the token.
|
||||
*/
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode: Node, ignoreTokenCallback: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback: (node: Node, token: SyntaxKind) => TextRange): number;
|
||||
function emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node, token: SyntaxKind) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
if (contextNode) {
|
||||
if (ignoreTokenCallback(contextNode, token)) {
|
||||
return tokenEndPos;
|
||||
}
|
||||
|
||||
const range = getTokenTextRangeCallback(contextNode, token);
|
||||
if (range) {
|
||||
tokenEndPos = range.end;
|
||||
}
|
||||
tokenPos = skipTrivia(currentSourceText, range ? range.pos : tokenPos);
|
||||
if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) {
|
||||
emitPos(tokenPos);
|
||||
}
|
||||
|
||||
emitPos(tokenEndPos);
|
||||
return tokenEndPos;
|
||||
}
|
||||
tokenPos = emitCallback(token, tokenPos);
|
||||
|
||||
if (range) tokenPos = range.end;
|
||||
if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) {
|
||||
emitPos(tokenPos);
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
function changeEmitSourcePos() {
|
||||
Debug.assert(!modifyLastSourcePos);
|
||||
modifyLastSourcePos = true;
|
||||
return tokenPos;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -706,6 +385,10 @@ namespace ts {
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = sourceFile;
|
||||
currentSourceText = currentSourceFile.text;
|
||||
|
||||
@ -738,6 +421,10 @@ namespace ts {
|
||||
* Gets the text for the source map.
|
||||
*/
|
||||
function getText() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return stringify({
|
||||
@ -755,6 +442,10 @@ namespace ts {
|
||||
* Gets the SourceMappingURL for the source map.
|
||||
*/
|
||||
function getSourceMappingURL() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (compilerOptions.inlineSourceMap) {
|
||||
// Encode the sourceMap into the sourceMap url
|
||||
const base64SourceMapText = convertToBase64(getText());
|
||||
@ -766,61 +457,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createSourceMapWriterWithExtendedDiagnostics(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const {
|
||||
initialize,
|
||||
reset,
|
||||
getSourceMapData,
|
||||
setSourceFile,
|
||||
emitPos,
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitTokenStart,
|
||||
emitTokenEnd,
|
||||
changeEmitSourcePos,
|
||||
stopOverridingSpan,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
} = createSourceMapWriterWorker(host, writer);
|
||||
return {
|
||||
initialize,
|
||||
reset,
|
||||
getSourceMapData,
|
||||
setSourceFile,
|
||||
emitPos(pos: number): void {
|
||||
performance.mark("sourcemapStart");
|
||||
emitPos(pos);
|
||||
performance.measure("sourceMapTime", "sourcemapStart");
|
||||
},
|
||||
emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void {
|
||||
performance.mark("emitSourcemap:emitStart");
|
||||
emitStart(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitStart");
|
||||
},
|
||||
emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void {
|
||||
performance.mark("emitSourcemap:emitEnd");
|
||||
emitEnd(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitEnd");
|
||||
},
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
performance.mark("emitSourcemap:emitTokenStart");
|
||||
tokenStartPos = emitTokenStart(token, tokenStartPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitTokenStart");
|
||||
return tokenStartPos;
|
||||
},
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
performance.mark("emitSourcemap:emitTokenEnd");
|
||||
tokenEndPos = emitTokenEnd(token, tokenEndPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitTokenEnd");
|
||||
return tokenEndPos;
|
||||
},
|
||||
changeEmitSourcePos,
|
||||
stopOverridingSpan,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
};
|
||||
}
|
||||
|
||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
function base64FormatEncode(inValue: number) {
|
||||
|
||||
@ -28,46 +28,25 @@ namespace ts {
|
||||
/**
|
||||
* Gets the transformed source files.
|
||||
*/
|
||||
getSourceFiles(): SourceFile[];
|
||||
transformed: 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.
|
||||
*/
|
||||
isSubstitutionEnabled(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* Determines whether before/after emit notifications should be raised in the pretty
|
||||
* printer when it emits a node.
|
||||
*/
|
||||
isEmitNotificationEnabled(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* Hook used by transformers to substitute expressions just before they
|
||||
* are emitted by the pretty printer.
|
||||
* Emits the substitute for a node, if one is available; otherwise, emits the node.
|
||||
*
|
||||
* @param emitContext The current emit context.
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is in an expression context.
|
||||
* @param emitCallback A callback used to emit the node or its substitute.
|
||||
*/
|
||||
onSubstituteNode(node: Node, isExpression: boolean): Node;
|
||||
emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
|
||||
/**
|
||||
* Hook used to allow transformers to capture state before or after
|
||||
* the printer emits a node.
|
||||
* Emits a node with possible notification.
|
||||
*
|
||||
* @param emitContext The current emit context.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback A callback used to emit the node.
|
||||
*/
|
||||
onEmitNode(node: Node, emitCallback: (node: Node) => void): void;
|
||||
|
||||
/**
|
||||
* Reset transient transformation properties on parse tree nodes.
|
||||
*/
|
||||
dispose(): void;
|
||||
emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
}
|
||||
|
||||
export interface TransformationContext extends LexicalEnvironment {
|
||||
@ -75,46 +54,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<T extends Node>(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<T extends Node>(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<T extends Node>(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<T extends Node>(node: T, range: TextRange): T;
|
||||
|
||||
/**
|
||||
* Hoists a function declaration to the containing scope.
|
||||
*/
|
||||
@ -139,7 +78,7 @@ namespace ts {
|
||||
* Hook used by transformers to substitute expressions just before they
|
||||
* are emitted by the pretty printer.
|
||||
*/
|
||||
onSubstituteNode?: (node: Node, isExpression: boolean) => Node;
|
||||
onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node;
|
||||
|
||||
/**
|
||||
* Enables before/after emit notifications in the pretty printer for the provided
|
||||
@ -157,7 +96,7 @@ namespace ts {
|
||||
* Hook used to allow transformers to capture state before or after
|
||||
* the printer emits a node.
|
||||
*/
|
||||
onEmitNode?: (node: Node, emit: (node: Node) => void) => void;
|
||||
onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@ -186,14 +125,6 @@ namespace ts {
|
||||
return transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
let nextTransformId = 1;
|
||||
|
||||
/**
|
||||
* Transforms an array of SourceFiles by passing them through each transformer.
|
||||
*
|
||||
@ -203,18 +134,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<TextRange>();
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
const parseTreeNodesWithAnnotations: Node[] = [];
|
||||
|
||||
let lastTokenSourceMapRangeNode: Node;
|
||||
let lastTokenSourceMapRangeToken: SyntaxKind;
|
||||
let lastTokenSourceMapRange: TextRange;
|
||||
let lexicalEnvironmentStackOffset = 0;
|
||||
let hoistedVariableDeclarations: VariableDeclaration[];
|
||||
let hoistedFunctionDeclarations: FunctionDeclaration[];
|
||||
@ -226,22 +149,14 @@ namespace ts {
|
||||
getCompilerOptions: () => host.getCompilerOptions(),
|
||||
getEmitResolver: () => resolver,
|
||||
getEmitHost: () => host,
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
getSourceMapRange,
|
||||
setSourceMapRange,
|
||||
getTokenSourceMapRange,
|
||||
setTokenSourceMapRange,
|
||||
getCommentRange,
|
||||
setCommentRange,
|
||||
hoistVariableDeclaration,
|
||||
hoistFunctionDeclaration,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
onSubstituteNode,
|
||||
onSubstituteNode: (emitContext, node) => node,
|
||||
enableSubstitution,
|
||||
isSubstitutionEnabled,
|
||||
onEmitNode,
|
||||
onEmitNode: (node, emitContext, emitCallback) => emitCallback(node, emitContext),
|
||||
enableEmitNotification,
|
||||
isEmitNotificationEnabled
|
||||
};
|
||||
@ -256,30 +171,9 @@ namespace ts {
|
||||
lexicalEnvironmentDisabled = true;
|
||||
|
||||
return {
|
||||
getSourceFiles: () => transformed,
|
||||
getTokenSourceMapRange,
|
||||
isSubstitutionEnabled,
|
||||
isEmitNotificationEnabled,
|
||||
onSubstituteNode: context.onSubstituteNode,
|
||||
onEmitNode: context.onEmitNode,
|
||||
dispose() {
|
||||
// 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.
|
||||
for (const node of parseTreeNodesWithAnnotations) {
|
||||
if (node.transformId === transformId) {
|
||||
node.transformId = 0;
|
||||
node.emitFlags = 0;
|
||||
node.commentRange = undefined;
|
||||
node.sourceMapRange = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
parseTreeNodesWithAnnotations.length = 0;
|
||||
}
|
||||
transformed,
|
||||
emitNodeWithSubstitution,
|
||||
emitNodeWithNotification
|
||||
};
|
||||
|
||||
/**
|
||||
@ -306,18 +200,29 @@ namespace ts {
|
||||
* Determines whether expression substitutions are enabled for the provided node.
|
||||
*/
|
||||
function isSubstitutionEnabled(node: Node) {
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.Substitution) !== 0;
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.Substitution) !== 0
|
||||
&& (getEmitFlags(node) & EmitFlags.NoSubstitution) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default hook for node substitutions.
|
||||
* Emits a node with possible substitution.
|
||||
*
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
* @param emitContext The current emit context.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node or its substitute.
|
||||
*/
|
||||
function onSubstituteNode(node: Node, isExpression: boolean) {
|
||||
return node;
|
||||
function emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
if (node) {
|
||||
if (isSubstitutionEnabled(node)) {
|
||||
const substitute = context.onSubstituteNode(emitContext, node);
|
||||
if (substitute && substitute !== node) {
|
||||
emitCallback(emitContext, substitute);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -333,154 +238,25 @@ namespace ts {
|
||||
*/
|
||||
function isEmitNotificationEnabled(node: Node) {
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0
|
||||
|| (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0;
|
||||
|| (getEmitFlags(node) & EmitFlags.AdviseOnEmitNode) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default hook for node emit.
|
||||
* Emits a node with possible emit notification.
|
||||
*
|
||||
* @param emitContext The current emit context.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void) {
|
||||
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<T extends Node>(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<T extends Node>(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;
|
||||
function emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
if (node) {
|
||||
if (isEmitNotificationEnabled(node)) {
|
||||
context.onEmitNode(emitContext, node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
|
||||
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<T extends Node>(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<T extends Node>(node: T, range: TextRange) {
|
||||
beforeSetAnnotation(node);
|
||||
node.commentRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -563,70 +339,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<T, U>(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U;
|
||||
function chain<T, U>(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<T>(...args: ((t: T) => T)[]): (t: T) => T;
|
||||
function compose<T>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
@ -147,7 +147,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);
|
||||
@ -211,7 +211,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;
|
||||
@ -271,8 +271,8 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const name = getMutableClone(<Identifier>target);
|
||||
context.setSourceMapRange(name, target);
|
||||
context.setCommentRange(name, target);
|
||||
setSourceMapRange(name, target);
|
||||
setCommentRange(name, target);
|
||||
emitAssignment(name, value, location, /*original*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,13 +144,6 @@ namespace ts {
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
hoistVariableDeclaration,
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
getCommentRange,
|
||||
setCommentRange,
|
||||
getSourceMapRange,
|
||||
setSourceMapRange,
|
||||
setTokenSourceMapRange,
|
||||
} = context;
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
@ -185,6 +178,10 @@ namespace ts {
|
||||
return transformSourceFile;
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
currentSourceFile = node;
|
||||
currentText = node.text;
|
||||
return visitNode(node, visitor, isSourceFile);
|
||||
@ -408,7 +405,7 @@ namespace ts {
|
||||
enclosingFunction = currentNode;
|
||||
if (currentNode.kind !== SyntaxKind.ArrowFunction) {
|
||||
enclosingNonArrowFunction = currentNode;
|
||||
if (!(currentNode.emitFlags & NodeEmitFlags.AsyncFunctionBody)) {
|
||||
if (!(getEmitFlags(currentNode) & EmitFlags.AsyncFunctionBody)) {
|
||||
enclosingNonAsyncFunctionBody = currentNode;
|
||||
}
|
||||
}
|
||||
@ -671,19 +668,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(
|
||||
@ -717,17 +714,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;
|
||||
}
|
||||
|
||||
@ -830,7 +827,7 @@ namespace ts {
|
||||
);
|
||||
|
||||
if (!constructor) {
|
||||
setNodeEmitFlags(block, NodeEmitFlags.NoComments);
|
||||
setEmitFlags(block, EmitFlags.NoComments);
|
||||
}
|
||||
|
||||
return block;
|
||||
@ -967,27 +964,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
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1008,23 +1005,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);
|
||||
}
|
||||
|
||||
@ -1057,7 +1054,7 @@ namespace ts {
|
||||
|
||||
// `declarationName` is the name of the local declaration for the parameter.
|
||||
const declarationName = getMutableClone(<Identifier>parameter.name);
|
||||
setNodeEmitFlags(declarationName, NodeEmitFlags.NoSourceMap);
|
||||
setEmitFlags(declarationName, EmitFlags.NoSourceMap);
|
||||
|
||||
// `expressionName` is the name of the parameter used in expressions.
|
||||
const expressionName = getSynthesizedClone(<Identifier>parameter.name);
|
||||
@ -1066,7 +1063,7 @@ namespace ts {
|
||||
|
||||
// var param = [];
|
||||
statements.push(
|
||||
setNodeEmitFlags(
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
@ -1078,7 +1075,7 @@ namespace ts {
|
||||
]),
|
||||
/*location*/ parameter
|
||||
),
|
||||
NodeEmitFlags.CustomPrologue
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
|
||||
@ -1111,7 +1108,7 @@ namespace ts {
|
||||
])
|
||||
);
|
||||
|
||||
setNodeEmitFlags(forStatement, NodeEmitFlags.CustomPrologue);
|
||||
setEmitFlags(forStatement, EmitFlags.CustomPrologue);
|
||||
startOnNewLine(forStatement);
|
||||
statements.push(forStatement);
|
||||
}
|
||||
@ -1136,7 +1133,7 @@ namespace ts {
|
||||
])
|
||||
);
|
||||
|
||||
setNodeEmitFlags(captureThisStatement, NodeEmitFlags.NoComments | NodeEmitFlags.CustomPrologue);
|
||||
setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
|
||||
setSourceMapRange(captureThisStatement, node);
|
||||
statements.push(captureThisStatement);
|
||||
}
|
||||
@ -1200,7 +1197,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(
|
||||
@ -1221,7 +1218,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;
|
||||
}
|
||||
|
||||
@ -1240,7 +1237,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;
|
||||
}
|
||||
|
||||
@ -1254,11 +1251,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: ObjectLiteralElementLike[] = [];
|
||||
@ -1309,7 +1306,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const func = transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined);
|
||||
setNodeEmitFlags(func, NodeEmitFlags.CapturesThis);
|
||||
setEmitFlags(func, EmitFlags.CapturesThis);
|
||||
return func;
|
||||
}
|
||||
|
||||
@ -1434,7 +1431,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
|
||||
@ -1452,7 +1449,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, isObjectLiteralElementLike, 0, numInitialProperties),
|
||||
/*location*/ undefined,
|
||||
node.multiLine
|
||||
),
|
||||
NodeEmitFlags.Indented
|
||||
EmitFlags.Indented
|
||||
)
|
||||
);
|
||||
if (node.multiLine) {
|
||||
@ -2067,16 +2064,16 @@ namespace ts {
|
||||
|
||||
const isAsyncBlockContainingAwait =
|
||||
enclosingNonArrowFunction
|
||||
&& (enclosingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody) !== 0
|
||||
&& (getEmitFlags(enclosingNonArrowFunction) & 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,
|
||||
@ -2855,7 +2852,7 @@ namespace ts {
|
||||
*
|
||||
* @param node The node to be printed.
|
||||
*/
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void) {
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
const savedEnclosingFunction = enclosingFunction;
|
||||
|
||||
if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis && isFunctionLike(node)) {
|
||||
@ -2863,7 +2860,7 @@ namespace ts {
|
||||
enclosingFunction = node;
|
||||
}
|
||||
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
|
||||
enclosingFunction = savedEnclosingFunction;
|
||||
}
|
||||
@ -2904,10 +2901,10 @@ namespace ts {
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(node: Node, isExpression: boolean) {
|
||||
node = previousOnSubstituteNode(node, isExpression);
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
|
||||
if (isExpression) {
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(node);
|
||||
}
|
||||
|
||||
@ -2995,7 +2992,7 @@ namespace ts {
|
||||
function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression {
|
||||
if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis
|
||||
&& enclosingFunction
|
||||
&& enclosingFunction.emitFlags & NodeEmitFlags.CapturesThis) {
|
||||
&& getEmitFlags(enclosingFunction) & EmitFlags.CapturesThis) {
|
||||
return createIdentifier("_this", /*location*/ node);
|
||||
}
|
||||
|
||||
@ -3013,7 +3010,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3022,18 +3019,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;
|
||||
}
|
||||
|
||||
@ -9,6 +9,10 @@ namespace ts {
|
||||
return transformSourceFile;
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
@ -616,7 +617,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// Do not hoist custom prologues.
|
||||
if (node.emitFlags & NodeEmitFlags.CustomPrologue) {
|
||||
if (getEmitFlags(node) & EmitFlags.CustomPrologue) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -1887,9 +1888,9 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function onSubstituteNode(node: Node, isExpression: boolean): Node {
|
||||
node = previousOnSubstituteNode(node, isExpression);
|
||||
if (isExpression) {
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node): Node {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
return node;
|
||||
@ -2585,7 +2586,7 @@ namespace ts {
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
setNodeEmitFlags(
|
||||
setEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
@ -2598,7 +2599,7 @@ namespace ts {
|
||||
/*multiLine*/ buildResult.length > 0
|
||||
)
|
||||
),
|
||||
NodeEmitFlags.ReuseTempVariableScope
|
||||
EmitFlags.ReuseTempVariableScope
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -821,14 +822,14 @@ namespace ts {
|
||||
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void): void {
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
bindingNameExportSpecifiersMap = bindingNameExportSpecifiersForFileMap[getOriginalNodeId(node)];
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
bindingNameExportSpecifiersMap = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,9 +840,9 @@ namespace ts {
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(node: Node, isExpression: boolean) {
|
||||
node = previousOnSubstituteNode(node, isExpression);
|
||||
if (isExpression) {
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
else if (isShorthandPropertyAssignment(node)) {
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -984,14 +986,14 @@ namespace ts {
|
||||
// Substitutions
|
||||
//
|
||||
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void): void {
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
exportFunctionForFile = exportFunctionForFileMap[getOriginalNodeId(node)];
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
exportFunctionForFile = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1002,9 +1004,9 @@ namespace ts {
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(node: Node, isExpression: boolean) {
|
||||
node = previousOnSubstituteNode(node, isExpression);
|
||||
if (isExpression) {
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(<Expression>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(<Identifier>operand);
|
||||
if (exportDeclaration) {
|
||||
const expr = createPrefix(node.operator, operand, node);
|
||||
setNodeEmitFlags(expr, NodeEmitFlags.NoSubstitution);
|
||||
setEmitFlags(expr, EmitFlags.NoSubstitution);
|
||||
const call = createExportExpression(<Identifier>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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,10 +24,6 @@ namespace ts {
|
||||
|
||||
export function transformTypeScript(context: TransformationContext) {
|
||||
const {
|
||||
getNodeEmitFlags,
|
||||
setNodeEmitFlags,
|
||||
setCommentRange,
|
||||
setSourceMapRange,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
hoistVariableDeclaration,
|
||||
@ -46,6 +42,10 @@ namespace ts {
|
||||
context.onEmitNode = onEmitNode;
|
||||
context.onSubstituteNode = onSubstituteNode;
|
||||
|
||||
// Enable substitution for property/element access to emit const enum values.
|
||||
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
|
||||
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
|
||||
|
||||
// These variables contain state that changes as we descend into the tree.
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentNamespace: ModuleDeclaration;
|
||||
@ -85,6 +85,10 @@ namespace ts {
|
||||
* @param node A SourceFile node.
|
||||
*/
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return visitNode(node, visitor, isSourceFile);
|
||||
}
|
||||
|
||||
@ -449,7 +453,7 @@ namespace ts {
|
||||
node = visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
setNodeEmitFlags(node, NodeEmitFlags.EmitEmitHelpers | node.emitFlags);
|
||||
setEmitFlags(node, EmitFlags.EmitEmitHelpers | getEmitFlags(node));
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -521,7 +525,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 +780,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 +1013,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 +1422,7 @@ namespace ts {
|
||||
moveRangePastDecorators(member)
|
||||
);
|
||||
|
||||
setNodeEmitFlags(helper, NodeEmitFlags.NoComments);
|
||||
setEmitFlags(helper, EmitFlags.NoComments);
|
||||
return helper;
|
||||
}
|
||||
|
||||
@ -1467,7 +1471,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 +1495,7 @@ namespace ts {
|
||||
moveRangePastDecorators(node)
|
||||
);
|
||||
|
||||
setNodeEmitFlags(result, NodeEmitFlags.NoComments);
|
||||
setEmitFlags(result, EmitFlags.NoComments);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1521,7 +1525,7 @@ namespace ts {
|
||||
transformDecorator(decorator),
|
||||
parameterOffset,
|
||||
/*location*/ decorator.expression);
|
||||
setNodeEmitFlags(helper, NodeEmitFlags.NoComments);
|
||||
setEmitFlags(helper, EmitFlags.NoComments);
|
||||
expressions.push(helper);
|
||||
}
|
||||
}
|
||||
@ -2324,11 +2328,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 +2379,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 +2538,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 +2548,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 +2588,7 @@ namespace ts {
|
||||
);
|
||||
|
||||
setOriginalNode(enumStatement, node);
|
||||
setNodeEmitFlags(enumStatement, emitFlags);
|
||||
setEmitFlags(enumStatement, emitFlags);
|
||||
statements.push(enumStatement);
|
||||
|
||||
if (isNamespaceExport(node)) {
|
||||
@ -2736,7 +2740,7 @@ namespace ts {
|
||||
// })(m1 || (m1 = {})); // trailing comment module
|
||||
//
|
||||
setCommentRange(statement, node);
|
||||
setNodeEmitFlags(statement, NodeEmitFlags.NoTrailingComments);
|
||||
setEmitFlags(statement, EmitFlags.NoTrailingComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
@ -2759,7 +2763,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 +2772,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 +2824,7 @@ namespace ts {
|
||||
);
|
||||
|
||||
setOriginalNode(moduleStatement, node);
|
||||
setNodeEmitFlags(moduleStatement, emitFlags);
|
||||
setEmitFlags(moduleStatement, emitFlags);
|
||||
statements.push(moduleStatement);
|
||||
return statements;
|
||||
}
|
||||
@ -2895,7 +2899,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 +2940,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const moduleReference = createExpressionFromEntityName(<EntityName>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 +3052,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 +3097,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 +3115,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 +3126,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;
|
||||
@ -3231,7 +3235,7 @@ namespace ts {
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void): void {
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
const savedApplicableSubstitutions = applicableSubstitutions;
|
||||
const savedCurrentSuperContainer = currentSuperContainer;
|
||||
// If we need to support substitutions for `super` in an async method,
|
||||
@ -3248,7 +3252,7 @@ namespace ts {
|
||||
applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers;
|
||||
}
|
||||
|
||||
previousOnEmitNode(node, emit);
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
|
||||
applicableSubstitutions = savedApplicableSubstitutions;
|
||||
currentSuperContainer = savedCurrentSuperContainer;
|
||||
@ -3261,9 +3265,9 @@ namespace ts {
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(node: Node, isExpression: boolean) {
|
||||
node = previousOnSubstituteNode(node, isExpression);
|
||||
if (isExpression) {
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
else if (isShorthandPropertyAssignment(node)) {
|
||||
@ -3294,17 +3298,15 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return substituteExpressionIdentifier(<Identifier>node);
|
||||
}
|
||||
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
case SyntaxKind.CallExpression:
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
|
||||
return substituteCallExpression(<CallExpression>node);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -3342,7 +3344,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);
|
||||
@ -3381,7 +3383,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
@ -3392,11 +3394,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
return substituteConstantValue(node);
|
||||
}
|
||||
|
||||
function substituteElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
@ -3407,9 +3409,39 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return substituteConstantValue(node);
|
||||
}
|
||||
|
||||
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression): LeftHandSideExpression {
|
||||
const constantValue = tryGetConstEnumValue(node);
|
||||
if (constantValue !== undefined) {
|
||||
const substitute = createLiteral(constantValue);
|
||||
setSourceMapRange(substitute, node);
|
||||
setCommentRange(substitute, node);
|
||||
if (!compilerOptions.removeComments) {
|
||||
const propertyName = isPropertyAccessExpression(node)
|
||||
? declarationNameToString(node.name)
|
||||
: getTextOfNode(node.argumentExpression);
|
||||
substitute.trailingComment = ` ${propertyName} `;
|
||||
}
|
||||
|
||||
setConstantValue(node, constantValue);
|
||||
return substitute;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function tryGetConstEnumValue(node: Node): number {
|
||||
if (compilerOptions.isolatedModules) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return isPropertyAccessExpression(node) || isElementAccessExpression(node)
|
||||
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
|
||||
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
return createPropertyAccess(
|
||||
|
||||
@ -494,10 +494,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<T extends Node> extends Array<T>, TextRange {
|
||||
@ -3175,7 +3172,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum NodeEmitFlags {
|
||||
export interface EmitNode {
|
||||
flags?: EmitFlags;
|
||||
commentRange?: TextRange;
|
||||
sourceMapRange?: TextRange;
|
||||
tokenSourceMapRanges?: Map<TextRange>;
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
constantValue?: number;
|
||||
}
|
||||
|
||||
/* @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.
|
||||
@ -3205,6 +3212,14 @@ namespace ts {
|
||||
CustomPrologue = 1 << 23, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum EmitContext {
|
||||
SourceFile, // Emitting a SourceFile
|
||||
Expression, // Emitting an Expression
|
||||
IdentifierName, // Emitting an IdentifierName
|
||||
Unspecified, // Emitting an otherwise unspecified node
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
/* @internal */
|
||||
export interface LexicalEnvironment {
|
||||
|
||||
@ -23,15 +23,15 @@ let c1 = Foo["C"].toString();
|
||||
|
||||
|
||||
//// [constEnumToStringWithComments.js]
|
||||
var x0 = 100 /* X */..toString();
|
||||
var x1 = 100 /* "X" */..toString();
|
||||
var x0 = 100 /* X */.toString();
|
||||
var x1 = 100 /* "X" */.toString();
|
||||
var y0 = 0.5 /* Y */.toString();
|
||||
var y1 = 0.5 /* "Y" */.toString();
|
||||
var z0 = 2 /* Z */..toString();
|
||||
var z1 = 2 /* "Z" */..toString();
|
||||
var a0 = -1 /* A */..toString();
|
||||
var a1 = -1 /* "A" */..toString();
|
||||
var z0 = 2 /* Z */.toString();
|
||||
var z1 = 2 /* "Z" */.toString();
|
||||
var a0 = -1 /* A */.toString();
|
||||
var a1 = -1 /* "A" */.toString();
|
||||
var b0 = -1.5 /* B */.toString();
|
||||
var b1 = -1.5 /* "B" */.toString();
|
||||
var c0 = -1 /* C */..toString();
|
||||
var c1 = -1 /* "C" */..toString();
|
||||
var c0 = -1 /* C */.toString();
|
||||
var c1 = -1 /* "C" */.toString();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user