mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Pulls transformation out of printFile to reduce number of closures. Also some additional cleanup.
This commit is contained in:
+10
-10
@@ -17136,7 +17136,7 @@ namespace ts {
|
||||
|
||||
function isArgumentsLocalBinding(node: Identifier): boolean {
|
||||
if (!isGeneratedIdentifier(node)) {
|
||||
node = getSourceTreeNodeOfType(node, isIdentifier);
|
||||
node = getParseTreeNode(node, isIdentifier);
|
||||
if (node) {
|
||||
return getReferencedValueSymbol(node) === argumentsSymbol;
|
||||
}
|
||||
@@ -17182,7 +17182,7 @@ namespace ts {
|
||||
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
|
||||
// node of the exported entity's container. Otherwise, return undefined.
|
||||
function getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration {
|
||||
node = getSourceTreeNodeOfType(node, isIdentifier);
|
||||
node = getParseTreeNode(node, isIdentifier);
|
||||
if (node) {
|
||||
// When resolving the export container for the name of a module or enum
|
||||
// declaration, we need to start resolution at the declaration's container.
|
||||
@@ -17220,7 +17220,7 @@ namespace ts {
|
||||
// When resolved as an expression identifier, if the given node references an import, return the declaration of
|
||||
// that import. Otherwise, return undefined.
|
||||
function getReferencedImportDeclaration(node: Identifier): Declaration {
|
||||
node = getSourceTreeNodeOfType(node, isIdentifier);
|
||||
node = getParseTreeNode(node, isIdentifier);
|
||||
if (node) {
|
||||
const symbol = getReferencedValueSymbol(node);
|
||||
if (symbol && symbol.flags & SymbolFlags.Alias) {
|
||||
@@ -17279,7 +17279,7 @@ namespace ts {
|
||||
// return the declaration of that entity. Otherwise, return undefined.
|
||||
function getReferencedDeclarationWithCollidingName(node: Identifier): Declaration {
|
||||
if (!isGeneratedIdentifier(node)) {
|
||||
node = getSourceTreeNodeOfType(node, isIdentifier);
|
||||
node = getParseTreeNode(node, isIdentifier);
|
||||
if (node) {
|
||||
const symbol = getReferencedValueSymbol(node);
|
||||
if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) {
|
||||
@@ -17294,7 +17294,7 @@ namespace ts {
|
||||
// Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an
|
||||
// existing name or might hide a name when compiled downlevel
|
||||
function isDeclarationWithCollidingName(node: Declaration): boolean {
|
||||
node = getSourceTreeNodeOfType(node, isDeclaration);
|
||||
node = getParseTreeNode(node, isDeclaration);
|
||||
if (node) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
if (symbol) {
|
||||
@@ -17306,7 +17306,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isValueAliasDeclaration(node: Node): boolean {
|
||||
node = getSourceTreeNode(node);
|
||||
node = getParseTreeNode(node);
|
||||
if (node === undefined) {
|
||||
// A synthesized node comes from an emit transformation and is always a value.
|
||||
return true;
|
||||
@@ -17332,7 +17332,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean {
|
||||
node = getSourceTreeNodeOfType(node, isImportEqualsDeclaration);
|
||||
node = getParseTreeNode(node, isImportEqualsDeclaration);
|
||||
if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
|
||||
// parent is not source file or it is not reference to internal module
|
||||
return false;
|
||||
@@ -17358,7 +17358,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
|
||||
node = getSourceTreeNode(node);
|
||||
node = getParseTreeNode(node);
|
||||
if (isAliasSymbolDeclaration(node)) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
if (symbol && getSymbolLinks(symbol).referenced) {
|
||||
@@ -17394,7 +17394,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getNodeCheckFlags(node: Node): NodeCheckFlags {
|
||||
node = getSourceTreeNode(node);
|
||||
node = getParseTreeNode(node);
|
||||
return node ? getNodeLinks(node).flags : undefined;
|
||||
}
|
||||
|
||||
@@ -17525,7 +17525,7 @@ namespace ts {
|
||||
|
||||
function getReferencedValueDeclaration(reference: Identifier): Declaration {
|
||||
if (!isGeneratedIdentifier(reference)) {
|
||||
reference = getSourceTreeNodeOfType(reference, isIdentifier);
|
||||
reference = getParseTreeNode(reference, isIdentifier);
|
||||
if (reference) {
|
||||
const symbol = getReferencedValueSymbol(reference);
|
||||
if (symbol) {
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace ts {
|
||||
let hasWrittenComment = false;
|
||||
let hasLastComment: boolean;
|
||||
let lastCommentEnd: number;
|
||||
let disabled: boolean = false;
|
||||
|
||||
return {
|
||||
reset,
|
||||
@@ -43,9 +44,15 @@ namespace ts {
|
||||
|
||||
if (node) {
|
||||
const { pos, end } = node.commentRange || node;
|
||||
const emitFlags = node.emitFlags;
|
||||
if ((pos < 0 && end < 0) || (pos === end)) {
|
||||
// Both pos and end are synthesized, so just emit the node without comments.
|
||||
emitCallback(node);
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
disableCommentsAndEmit(node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let commentStart: number;
|
||||
@@ -53,7 +60,6 @@ namespace ts {
|
||||
commentStart = performance.mark();
|
||||
}
|
||||
|
||||
const emitFlags = node.emitFlags;
|
||||
const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement;
|
||||
const skipLeadingComments = pos < 0 || (emitFlags & NodeEmitFlags.NoLeadingComments) !== 0;
|
||||
const skipTrailingComments = end < 0 || (emitFlags & NodeEmitFlags.NoTrailingComments) !== 0;
|
||||
@@ -85,13 +91,19 @@ namespace ts {
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
emitCallback(node);
|
||||
commentStart = performance.mark();
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
disableCommentsAndEmit(node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
}
|
||||
|
||||
// Restore previous container state.
|
||||
containerPos = savedContainerPos;
|
||||
containerEnd = savedContainerEnd;
|
||||
@@ -269,6 +281,18 @@ namespace ts {
|
||||
currentText = currentSourceFile.text;
|
||||
currentLineMap = getLineStarts(currentSourceFile);
|
||||
detachedCommentsInfo = undefined;
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
function disableCommentsAndEmit(node: Node, emitCallback: (node: Node) => void): void {
|
||||
if (disabled) {
|
||||
emitCallback(node);
|
||||
}
|
||||
else {
|
||||
disabled = true;
|
||||
emitCallback(node);
|
||||
disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function hasDetachedComments(pos: number) {
|
||||
|
||||
@@ -1882,11 +1882,11 @@ namespace ts {
|
||||
|
||||
export function setOriginalNode<T extends Node>(node: T, original: Node): T {
|
||||
node.original = original;
|
||||
if (original && original.transformId && !node.transformId) {
|
||||
node.transformId = original.transformId;
|
||||
node.emitFlags = original.emitFlags;
|
||||
node.commentRange = original.commentRange;
|
||||
node.sourceMapRange = original.sourceMapRange;
|
||||
if (original) {
|
||||
const { emitFlags, commentRange, sourceMapRange } = original;
|
||||
if (emitFlags) node.emitFlags = emitFlags;
|
||||
if (commentRange) node.commentRange = commentRange;
|
||||
if (sourceMapRange) node.sourceMapRange = sourceMapRange;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
+2517
-2530
File diff suppressed because it is too large
Load Diff
+93
-49
@@ -23,7 +23,52 @@ namespace ts {
|
||||
EmitNotifications = 1 << 1,
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TransformationResult {
|
||||
/**
|
||||
* Gets the transformed source files.
|
||||
*/
|
||||
getSourceFiles(): SourceFile[];
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange;
|
||||
|
||||
/**
|
||||
* Determines whether expression substitutions are enabled for the provided node.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is in an expression context.
|
||||
*/
|
||||
onSubstituteNode(node: Node, isExpression: boolean): Node;
|
||||
|
||||
/**
|
||||
* Hook used to allow transformers to capture state before or after
|
||||
* the printer emits a node.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
export interface TransformationContext extends LexicalEnvironment {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getEmitResolver(): EmitResolver;
|
||||
@@ -155,7 +200,7 @@ namespace ts {
|
||||
* @param sourceFiles An array of source files
|
||||
* @param transforms An array of Transformers.
|
||||
*/
|
||||
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]) {
|
||||
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult {
|
||||
const transformId = nextTransformId;
|
||||
nextTransformId++;
|
||||
|
||||
@@ -163,7 +208,7 @@ namespace ts {
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
const sourceTreeNodesWithAnnotations: Node[] = [];
|
||||
const parseTreeNodesWithAnnotations: Node[] = [];
|
||||
|
||||
let lastTokenSourceMapRangeNode: Node;
|
||||
let lastTokenSourceMapRangeToken: SyntaxKind;
|
||||
@@ -171,7 +216,6 @@ namespace ts {
|
||||
let lexicalEnvironmentStackOffset = 0;
|
||||
let hoistedVariableDeclarations: VariableDeclaration[];
|
||||
let hoistedFunctionDeclarations: FunctionDeclaration[];
|
||||
let currentSourceFile: SourceFile;
|
||||
let lexicalEnvironmentDisabled: boolean;
|
||||
|
||||
// The transformation context is provided to each transformer as part of transformer
|
||||
@@ -204,7 +248,34 @@ namespace ts {
|
||||
const transformation = chain(...transformers)(context);
|
||||
|
||||
// Transform each source file.
|
||||
return map(sourceFiles, transformSourceFile);
|
||||
const transformed = map(sourceFiles, transformSourceFile);
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms a source file.
|
||||
@@ -216,21 +287,7 @@ namespace ts {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
currentSourceFile = sourceFile;
|
||||
sourceFile = transformation(sourceFile);
|
||||
|
||||
// Cleanup source tree nodes with annotations
|
||||
for (const node of sourceTreeNodesWithAnnotations) {
|
||||
if (node.transformId === transformId) {
|
||||
node.transformId = 0;
|
||||
node.emitFlags = 0;
|
||||
node.commentRange = undefined;
|
||||
node.sourceMapRange = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
sourceTreeNodesWithAnnotations.length = 0;
|
||||
return sourceFile;
|
||||
return transformation(sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,15 +338,6 @@ namespace ts {
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(node: Node, emit: (node: Node) => void) {
|
||||
// Ensure that lexical environment modifications are disabled during the print phase.
|
||||
if (!lexicalEnvironmentDisabled) {
|
||||
const savedLexicalEnvironmentDisabled = lexicalEnvironmentDisabled;
|
||||
lexicalEnvironmentDisabled = true;
|
||||
emit(node);
|
||||
lexicalEnvironmentDisabled = savedLexicalEnvironmentDisabled;
|
||||
return;
|
||||
}
|
||||
|
||||
emit(node);
|
||||
}
|
||||
|
||||
@@ -300,12 +348,12 @@ namespace ts {
|
||||
* @param node The node.
|
||||
*/
|
||||
function beforeSetAnnotation(node: Node) {
|
||||
node.transformId = transformId;
|
||||
if ((node.flags & NodeFlags.Synthesized) === 0) {
|
||||
if ((node.flags & NodeFlags.Synthesized) === 0 && node.transformId !== transformId) {
|
||||
// To avoid holding onto transformation artifacts, we keep track of any
|
||||
// source tree node we are annotating. This allows us to clean them up after
|
||||
// parse tree node we are annotating. This allows us to clean them up after
|
||||
// all transformations have completed.
|
||||
sourceTreeNodesWithAnnotations.push(node);
|
||||
parseTreeNodesWithAnnotations.push(node);
|
||||
node.transformId = transformId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +366,7 @@ namespace ts {
|
||||
* @param node The node.
|
||||
*/
|
||||
function getNodeEmitFlags(node: Node) {
|
||||
return node.emitFlags & ~NodeEmitFlags.HasNodeEmitFlags;
|
||||
return node.emitFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,7 +377,7 @@ namespace ts {
|
||||
*/
|
||||
function setNodeEmitFlags<T extends Node>(node: T, emitFlags: NodeEmitFlags) {
|
||||
beforeSetAnnotation(node);
|
||||
node.emitFlags = emitFlags | NodeEmitFlags.HasNodeEmitFlags;
|
||||
node.emitFlags = emitFlags;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -520,7 +568,11 @@ namespace ts {
|
||||
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 = arrayOf<(t: T) => (u: U) => U>(arguments);
|
||||
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) {
|
||||
@@ -549,7 +601,11 @@ namespace ts {
|
||||
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 = arrayOf(arguments);
|
||||
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) {
|
||||
@@ -568,16 +624,4 @@ namespace ts {
|
||||
return t => t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an array from an ArrayLike.
|
||||
*/
|
||||
function arrayOf<T>(arrayLike: ArrayLike<T>) {
|
||||
const length = arrayLike.length;
|
||||
const array: T[] = new Array<T>(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = arrayLike[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -1425,15 +1425,13 @@ namespace ts {
|
||||
// If we are here it is most likely because our expression is a destructuring assignment.
|
||||
switch (node.expression.kind) {
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return createStatement(
|
||||
visitParenthesizedExpression(<ParenthesizedExpression>node.expression, /*needsDestructuringValue*/ false),
|
||||
/*location*/ node
|
||||
return updateStatement(node,
|
||||
visitParenthesizedExpression(<ParenthesizedExpression>node.expression, /*needsDestructuringValue*/ false)
|
||||
);
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return createStatement(
|
||||
visitBinaryExpression(<BinaryExpression>node.expression, /*needsDestructuringValue*/ false),
|
||||
/*location*/ node
|
||||
return updateStatement(node,
|
||||
visitBinaryExpression(<BinaryExpression>node.expression, /*needsDestructuringValue*/ false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2831,7 +2829,7 @@ namespace ts {
|
||||
// Only substitute the identifier if we have enabled substitutions for block-scoped
|
||||
// bindings.
|
||||
if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) {
|
||||
const original = getSourceTreeNodeOfType(node, isIdentifier);
|
||||
const original = getParseTreeNode(node, isIdentifier);
|
||||
if (original && isNameOfDeclarationWithCollidingName(original)) {
|
||||
return getGeneratedNameForNode(original);
|
||||
}
|
||||
|
||||
@@ -2767,11 +2767,6 @@ namespace ts {
|
||||
&& resolver.isTopLevelValueImportEqualsWithEntityName(node));
|
||||
}
|
||||
|
||||
function disableCommentsRecursive(node: Node) {
|
||||
setNodeEmitFlags(node, NodeEmitFlags.NoComments | getNodeEmitFlags(node));
|
||||
forEachChild(node, disableCommentsRecursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an import equals declaration.
|
||||
*
|
||||
@@ -2787,7 +2782,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
const moduleReference = createExpressionFromEntityName(<EntityName>node.moduleReference);
|
||||
disableCommentsRecursive(moduleReference);
|
||||
setNodeEmitFlags(moduleReference, NodeEmitFlags.NoComments | NodeEmitFlags.NoNestedComments);
|
||||
|
||||
if (isNamedExternalModuleExport(node) || !isNamespaceExport(node)) {
|
||||
// export var ${name} = ${moduleReference};
|
||||
// var ${name} = ${moduleReference};
|
||||
|
||||
+14
-16
@@ -2984,21 +2984,21 @@ namespace ts {
|
||||
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
|
||||
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
|
||||
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
|
||||
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module.
|
||||
SingleLine = 1 << 6, // The contents of this node should be emitted on a single line.
|
||||
AdviseOnEmitNode = 1 << 7, // The printer should invoke the onEmitNode callback when printing this node.
|
||||
NoSubstitution = 1 << 8, // Disables further substitution of an expression.
|
||||
CapturesThis = 1 << 9, // The function captures a lexical `this`
|
||||
NoLeadingSourceMap = 1 << 10, // Do not emit a leading source map location for this node.
|
||||
NoTrailingSourceMap = 1 << 11, // Do not emit a trailing source map location for this node.
|
||||
SingleLine = 1 << 5, // The contents of this node should be emitted on a single line.
|
||||
AdviseOnEmitNode = 1 << 6, // The printer should invoke the onEmitNode callback when printing this node.
|
||||
NoSubstitution = 1 << 7, // Disables further substitution of an expression.
|
||||
CapturesThis = 1 << 8, // The function captures a lexical `this`
|
||||
NoLeadingSourceMap = 1 << 9, // Do not emit a leading source map location for this node.
|
||||
NoTrailingSourceMap = 1 << 10, // Do not emit a trailing source map location for this node.
|
||||
NoSourceMap = NoLeadingSourceMap | NoTrailingSourceMap, // Do not emit a source map location for this node.
|
||||
NoNestedSourceMaps = 1 << 12, // Do not emit source map locations for children of this node.
|
||||
NoTokenLeadingSourceMaps = 1 << 13, // Do not emit leading source map location for token nodes.
|
||||
NoTokenTrailingSourceMaps = 1 << 14, // Do not emit trailing source map location for token nodes.
|
||||
NoNestedSourceMaps = 1 << 11, // Do not emit source map locations for children of this node.
|
||||
NoTokenLeadingSourceMaps = 1 << 12, // Do not emit leading source map location for token nodes.
|
||||
NoTokenTrailingSourceMaps = 1 << 13, // Do not emit trailing source map location for token nodes.
|
||||
NoTokenSourceMaps = NoTokenLeadingSourceMaps | NoTokenTrailingSourceMaps, // Do not emit source map locations for tokens of this node.
|
||||
NoLeadingComments = 1 << 15, // Do not emit leading comments for this node.
|
||||
NoTrailingComments = 1 << 16, // Do not emit trailing comments for this node.
|
||||
NoLeadingComments = 1 << 14, // Do not emit leading comments for this node.
|
||||
NoTrailingComments = 1 << 15, // Do not emit trailing comments for this node.
|
||||
NoComments = NoLeadingComments | NoTrailingComments, // Do not emit comments for this node.
|
||||
NoNestedComments = 1 << 16,
|
||||
ExportName = 1 << 17, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
|
||||
LocalName = 1 << 18, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
|
||||
Indented = 1 << 19, // Adds an explicit extra indentation level for class and function bodies when printing (used to match old emitter).
|
||||
@@ -3007,10 +3007,8 @@ namespace ts {
|
||||
// TODO(rbuckton): These should be removed once source maps are aligned with the old
|
||||
// emitter and new baselines are taken. This exists solely to
|
||||
// align with the old emitter.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 21, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 22, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
|
||||
HasNodeEmitFlags = 1 << 31, // Indicates the node has emit flags set.
|
||||
SourceMapEmitOpenBraceAsToken = 1 << 20, // Emits the open brace of a block function body as a source mapped token.
|
||||
SourceMapAdjustRestParameterLoop = 1 << 21, // Emits adjusted source map positions for a ForStatement generated when transforming a rest parameter for ES5/3.
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
|
||||
+109
-11
@@ -1888,27 +1888,55 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function isSourceTreeNode(node: Node): boolean {
|
||||
/**
|
||||
* Gets a value indicating whether a node originated in the parse tree.
|
||||
*
|
||||
* @param node The node to test.
|
||||
*/
|
||||
export function isParseTreeNode(node: Node): boolean {
|
||||
return (node.flags & NodeFlags.Synthesized) === 0;
|
||||
}
|
||||
|
||||
export function getSourceTreeNode(node: Node): Node {
|
||||
if (isSourceTreeNode(node)) {
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode(node: Node): Node;
|
||||
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @param nodeTest A callback used to ensure the correct type of parse tree node is returned.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
|
||||
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (isParseTreeNode(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node = getOriginalNode(node);
|
||||
|
||||
if (isSourceTreeNode(node)) {
|
||||
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getSourceTreeNodeOfType<T extends Node>(node: T, nodeTest: (node: Node) => node is T): T {
|
||||
const source = getSourceTreeNode(node);
|
||||
return source && nodeTest(source) ? source : undefined;
|
||||
export function getOriginalSourceFiles(sourceFiles: SourceFile[]) {
|
||||
const originalSourceFiles: SourceFile[] = [];
|
||||
for (const sourceFile of sourceFiles) {
|
||||
const originalSourceFile = getParseTreeNode(sourceFile, isSourceFile);
|
||||
if (originalSourceFile) {
|
||||
originalSourceFiles.push(originalSourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
return originalSourceFiles;
|
||||
}
|
||||
|
||||
export function getOriginalNodeId(node: Node) {
|
||||
@@ -2419,6 +2447,80 @@ namespace ts {
|
||||
declarationFilePath: string;
|
||||
}
|
||||
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile) {
|
||||
const options = host.getCompilerOptions();
|
||||
if (options.outFile || options.out) {
|
||||
const moduleKind = getEmitModuleKind(options);
|
||||
const moduleEmitEnabled = moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
|
||||
const sourceFiles = host.getSourceFiles();
|
||||
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
|
||||
return filter(sourceFiles, moduleEmitEnabled ? isNonDeclarationFile : isBundleEmitNonExternalModule);
|
||||
}
|
||||
else {
|
||||
const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
|
||||
return filter(sourceFiles, isNonDeclarationFile);
|
||||
}
|
||||
}
|
||||
|
||||
function isNonDeclarationFile(sourceFile: SourceFile) {
|
||||
return !isDeclarationFile(sourceFile);
|
||||
}
|
||||
|
||||
function isBundleEmitNonExternalModule(sourceFile: SourceFile) {
|
||||
return !isDeclarationFile(sourceFile) && !isExternalModule(sourceFile);
|
||||
}
|
||||
|
||||
export function forEachEmitFile(host: EmitHost, sourceFiles: SourceFile[],
|
||||
action: (jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) => void) {
|
||||
const options = host.getCompilerOptions();
|
||||
// Emit on each source file
|
||||
if (options.outFile || options.out) {
|
||||
onBundledEmit(host, sourceFiles);
|
||||
}
|
||||
else {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
if (!isDeclarationFile(sourceFile)) {
|
||||
onSingleFileEmit(host, sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
|
||||
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
|
||||
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
|
||||
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
|
||||
let extension = ".js";
|
||||
if (options.jsx === JsxEmit.Preserve) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
// TypeScript source file preserving JSX syntax
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = !isSourceFileJavaScript(sourceFile) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
|
||||
action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false);
|
||||
}
|
||||
|
||||
function onBundledEmit(host: EmitHost, sourceFiles: SourceFile[]) {
|
||||
if (sourceFiles.length) {
|
||||
const jsFilePath = options.outFile || options.out;
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
|
||||
action(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, /*isBundledEmit*/ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.sourceMap ? jsFilePath + ".map" : undefined;
|
||||
}
|
||||
|
||||
export function forEachExpectedEmitFile(host: EmitHost,
|
||||
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
|
||||
targetSourceFile?: SourceFile) {
|
||||
@@ -2479,10 +2581,6 @@ namespace ts {
|
||||
action(emitFileNames, bundledSources, /*isBundledEmit*/true);
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.sourceMap ? jsFilePath + ".map" : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
|
||||
|
||||
Reference in New Issue
Block a user