diff --git a/scripts/perf-result-post.js b/scripts/perf-result-post.js
index 79d90d40c5aab..337729128d261 100644
--- a/scripts/perf-result-post.js
+++ b/scripts/perf-result-post.js
@@ -3,45 +3,86 @@
// Must reference esnext.asynciterable lib, since octokit uses AsyncIterable internally
const { Octokit } = require("@octokit/rest");
const fs = require("fs");
+const ado = require("azure-devops-node-api");
+const { default: fetch } = require("node-fetch");
-const requester = process.env.requesting_user;
-const source = process.env.source_issue;
-const postedComment = process.env.status_comment;
-console.log(`Loading fragment from ${process.argv[3]}...`);
-const outputTableText = fs.readFileSync(process.argv[3], { encoding: "utf8" });
-console.log(`Fragment contents:
-${outputTableText}`);
-const gh = new Octokit({
- auth: process.argv[2]
-});
-gh.issues.createComment({
- issue_number: +source,
- owner: "Microsoft",
- repo: "TypeScript",
- body: `@${requester}
-The results of the perf run you requested are in!
- Here they are:
-${outputTableText}
-
`
-}).then(async data => {
- console.log(`Results posted!`);
- const newCommentUrl = data.data.html_url;
- const comment = await gh.issues.getComment({
- owner: "Microsoft",
- repo: "TypeScript",
- comment_id: +postedComment
- });
- const newBody = `${comment.data.body}
-
-Update: [The results are in!](${newCommentUrl})`;
- return await gh.issues.updateComment({
- owner: "Microsoft",
- repo: "TypeScript",
- comment_id: +postedComment,
- body: newBody
- });
-}).catch(e => {
+async function main() {
+ const source = process.env.SOURCE_ISSUE;
+ if (!source) throw new Error("SOURCE_ISSUE environment variable not set.");
+
+ const requester = process.env.REQUESTING_USER;
+ if (!requester) throw new Error("REQUESTING_USER environment variable not set.");
+
+ const buildId = process.env.BUILD_BUILDID;
+ if (!requester) throw new Error("BUILD_BUILDID environment variable not set.");
+
+ const postedComment = process.env.STATUS_COMMENT;
+ if (!postedComment) throw new Error("STATUS_COMMENT environment variable not set.");
+
+ const [auth, fragment, includeArtifact] = process.argv.slice(2);
+ if (!auth) throw new Error("First argument must be a GitHub auth token.");
+ if (!fragment) throw new Error("Second argument must be a path to an HTML fragment.");
+
+ const gh = new Octokit({ auth });
+ try {
+ console.log(`Loading fragment from ${fragment}...`);
+ const outputTableText = fs.readFileSync(fragment, { encoding: "utf8" });
+ console.log(`Fragment contents:\n${outputTableText}`);
+
+ let benchmarkText = "";
+ if (includeArtifact === "--include-artifact") {
+ // post a link to the benchmark file
+ const cli = new ado.WebApi("https://typescript.visualstudio.com/defaultcollection", ado.getHandlerFromToken("")); // Empty token, anon auth
+ const build = await cli.getBuildApi();
+ const artifact = await build.getArtifact("typescript", +buildId, "benchmark");
+ const updatedUrl = new URL(artifact.resource.url);
+ updatedUrl.search = `artifactName=benchmark&fileId=${artifact.resource.data}&fileName=manifest`;
+ const resp = await (await fetch(`${updatedUrl}`)).json();
+ for (const file of resp.items) {
+ if (/[\\/]linux\.benchmark$/.test(file.path)) {
+ const benchmarkUrl = new URL(artifact.resource.url);
+ benchmarkUrl.search = `artifactName=benchmark&fileId=${file.blob.id}&fileName=linux.benchmark`;
+ benchmarkText = `\nDeveloper Information:
Download Benchmark
\n`;
+ break;
+ }
+ }
+ }
+
+ const data = await gh.issues.createComment({
+ issue_number: +source,
+ owner: "Microsoft",
+ repo: "TypeScript",
+ body: `@${requester}\nThe results of the perf run you requested are in!\n Here they are:
\n${outputTableText}\n
${benchmarkText} `
+ });
+
+ console.log(`Results posted!`);
+ const newCommentUrl = data.data.html_url;
+ const comment = await gh.issues.getComment({
+ owner: "Microsoft",
+ repo: "TypeScript",
+ comment_id: +postedComment
+ });
+ const newBody = `${comment.data.body}\n\nUpdate: [The results are in!](${newCommentUrl})`;
+ await gh.issues.updateComment({
+ owner: "Microsoft",
+ repo: "TypeScript",
+ comment_id: +postedComment,
+ body: newBody
+ });
+ }
+ catch (e) {
+ const gh = new Octokit({ auth });
+ await gh.issues.createComment({
+ issue_number: +source,
+ owner: "Microsoft",
+ repo: "TypeScript",
+ body: `Hey @${requester}, something went wrong when publishing results. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${buildId}&_a=summary)).`
+ });
+ }
+}
+
+main().catch(e => {
console.error(e);
process.exit(1);
});
diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 365a3d36515af..9323ee4d07ba1 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -227,6 +227,7 @@ namespace ts {
const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
+ const bindBinaryExpressionFlow = createBindBinaryExpressionFlow();
/**
* Inside the binder, we may create a diagnostic for an as-yet unbound node (with potentially no parent pointers, implying no accessible source file)
@@ -1500,132 +1501,110 @@ namespace ts {
bindAssignmentTargetFlow(node.left);
}
- const enum BindBinaryExpressionFlowState {
- BindThenBindChildren,
- MaybeBindLeft,
- BindToken,
- BindRight,
- FinishBind
- }
-
- function bindBinaryExpressionFlow(node: BinaryExpression) {
- const workStacks: {
- expr: BinaryExpression[],
- state: BindBinaryExpressionFlowState[],
- inStrictMode: (boolean | undefined)[],
- parent: (Node | undefined)[],
- } = {
- expr: [node],
- state: [BindBinaryExpressionFlowState.MaybeBindLeft],
- inStrictMode: [undefined],
- parent: [undefined],
- };
- let stackIndex = 0;
- while (stackIndex >= 0) {
- node = workStacks.expr[stackIndex];
- switch (workStacks.state[stackIndex]) {
- case BindBinaryExpressionFlowState.BindThenBindChildren: {
- // This state is used only when recuring, to emulate the work that `bind` does before
- // reaching `bindChildren`. A normal call to `bindBinaryExpressionFlow` will already have done this work.
- setParent(node, parent);
- const saveInStrictMode = inStrictMode;
- bindWorker(node);
- const saveParent = parent;
- parent = node;
-
- advanceState(BindBinaryExpressionFlowState.MaybeBindLeft, saveInStrictMode, saveParent);
- break;
- }
- case BindBinaryExpressionFlowState.MaybeBindLeft: {
- const operator = node.operatorToken.kind;
- // TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
- // we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
- // For now, though, since the common cases are chained `+`, leaving it recursive is fine
- if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken ||
- isLogicalOrCoalescingAssignmentOperator(operator)) {
- if (isTopLevelLogicalExpression(node)) {
- const postExpressionLabel = createBranchLabel();
- bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);
- currentFlow = finishFlowLabel(postExpressionLabel);
- }
- else {
- bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!);
- }
- completeNode();
- }
- else {
- advanceState(BindBinaryExpressionFlowState.BindToken);
- maybeBind(node.left);
- }
- break;
- }
- case BindBinaryExpressionFlowState.BindToken: {
- if (node.operatorToken.kind === SyntaxKind.CommaToken) {
- maybeBindExpressionFlowIfCall(node.left);
- }
- advanceState(BindBinaryExpressionFlowState.BindRight);
- maybeBind(node.operatorToken);
- break;
- }
- case BindBinaryExpressionFlowState.BindRight: {
- advanceState(BindBinaryExpressionFlowState.FinishBind);
- maybeBind(node.right);
- break;
+ function createBindBinaryExpressionFlow() {
+ interface WorkArea {
+ stackIndex: number;
+ skip: boolean;
+ inStrictModeStack: (boolean | undefined)[];
+ parentStack: (Node | undefined)[];
+ }
+
+ return createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, /*foldState*/ undefined);
+
+ function onEnter(node: BinaryExpression, state: WorkArea | undefined) {
+ if (state) {
+ state.stackIndex++;
+ // Emulate the work that `bind` does before reaching `bindChildren`. A normal call to
+ // `bindBinaryExpressionFlow` will already have done this work.
+ setParent(node, parent);
+ const saveInStrictMode = inStrictMode;
+ bindWorker(node);
+ const saveParent = parent;
+ parent = node;
+ state.skip = false;
+ state.inStrictModeStack[state.stackIndex] = saveInStrictMode;
+ state.parentStack[state.stackIndex] = saveParent;
+ }
+ else {
+ state = {
+ stackIndex: 0,
+ skip: false,
+ inStrictModeStack: [undefined],
+ parentStack: [undefined]
+ };
+ }
+ // TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
+ // we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
+ // For now, though, since the common cases are chained `+`, leaving it recursive is fine
+ const operator = node.operatorToken.kind;
+ if (operator === SyntaxKind.AmpersandAmpersandToken ||
+ operator === SyntaxKind.BarBarToken ||
+ operator === SyntaxKind.QuestionQuestionToken ||
+ isLogicalOrCoalescingAssignmentOperator(operator)) {
+ if (isTopLevelLogicalExpression(node)) {
+ const postExpressionLabel = createBranchLabel();
+ bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);
+ currentFlow = finishFlowLabel(postExpressionLabel);
}
- case BindBinaryExpressionFlowState.FinishBind: {
- const operator = node.operatorToken.kind;
- if (isAssignmentOperator(operator) && !isAssignmentTarget(node)) {
- bindAssignmentTargetFlow(node.left);
- if (operator === SyntaxKind.EqualsToken && node.left.kind === SyntaxKind.ElementAccessExpression) {
- const elementAccess = node.left;
- if (isNarrowableOperand(elementAccess.expression)) {
- currentFlow = createFlowMutation(FlowFlags.ArrayMutation, currentFlow, node);
- }
- }
- }
- completeNode();
- break;
+ else {
+ bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!);
}
- default: return Debug.fail(`Invalid state ${workStacks.state[stackIndex]} for bindBinaryExpressionFlow`);
+ state.skip = true;
}
+ return state;
}
- /**
- * Note that `advanceState` sets the _current_ head state, and that `maybeBind` potentially pushes on a new
- * head state; so `advanceState` must be called before any `maybeBind` during a state's execution.
- */
- function advanceState(state: BindBinaryExpressionFlowState, isInStrictMode?: boolean, parent?: Node) {
- workStacks.state[stackIndex] = state;
- if (isInStrictMode !== undefined) {
- workStacks.inStrictMode[stackIndex] = isInStrictMode;
+ function onLeft(left: Expression, state: WorkArea, _node: BinaryExpression) {
+ if (!state.skip) {
+ return maybeBind(left);
}
- if (parent !== undefined) {
- workStacks.parent[stackIndex] = parent;
+ }
+
+ function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, node: BinaryExpression) {
+ if (!state.skip) {
+ if (operatorToken.kind === SyntaxKind.CommaToken) {
+ maybeBindExpressionFlowIfCall(node.left);
+ }
+ bind(operatorToken);
}
}
- function completeNode() {
- if (workStacks.inStrictMode[stackIndex] !== undefined) {
- inStrictMode = workStacks.inStrictMode[stackIndex]!;
- parent = workStacks.parent[stackIndex]!;
+ function onRight(right: Expression, state: WorkArea, _node: BinaryExpression) {
+ if (!state.skip) {
+ return maybeBind(right);
}
- stackIndex--;
}
- /**
- * If `node` is a BinaryExpression, adds it to the local work stack, otherwise recursively binds it
- */
+ function onExit(node: BinaryExpression, state: WorkArea) {
+ if (!state.skip) {
+ const operator = node.operatorToken.kind;
+ if (isAssignmentOperator(operator) && !isAssignmentTarget(node)) {
+ bindAssignmentTargetFlow(node.left);
+ if (operator === SyntaxKind.EqualsToken && node.left.kind === SyntaxKind.ElementAccessExpression) {
+ const elementAccess = node.left;
+ if (isNarrowableOperand(elementAccess.expression)) {
+ currentFlow = createFlowMutation(FlowFlags.ArrayMutation, currentFlow, node);
+ }
+ }
+ }
+ }
+ const savedInStrictMode = state.inStrictModeStack[state.stackIndex];
+ const savedParent = state.parentStack[state.stackIndex];
+ if (savedInStrictMode !== undefined) {
+ inStrictMode = savedInStrictMode;
+ }
+ if (savedParent !== undefined) {
+ parent = savedParent;
+ }
+ state.skip = false;
+ state.stackIndex--;
+ }
+
function maybeBind(node: Node) {
if (node && isBinaryExpression(node) && !isDestructuringAssignment(node)) {
- stackIndex++;
- workStacks.expr[stackIndex] = node;
- workStacks.state[stackIndex] = BindBinaryExpressionFlowState.BindThenBindChildren;
- workStacks.inStrictMode[stackIndex] = undefined;
- workStacks.parent[stackIndex] = undefined;
- }
- else {
- bind(node);
+ return node;
}
+ bind(node);
}
}
diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts
index 8d14c9c1ee5d7..adf968fe2c7bd 100644
--- a/src/compiler/debug.ts
+++ b/src/compiler/debug.ts
@@ -275,6 +275,14 @@ namespace ts {
}
}
+ /**
+ * Asserts a value has the specified type in typespace only (does not perform a runtime assertion).
+ * This is useful in cases where we switch on `node.kind` and can be reasonably sure the type is accurate, and
+ * as a result can reduce the number of unnecessary casts.
+ */
+ export function type(value: unknown): asserts value is T;
+ export function type(_value: unknown) { }
+
export function getFunctionName(func: AnyFunction) {
if (typeof func !== "function") {
return "";
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 24174483fdc6d..d7086a4193343 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -1,6 +1,5 @@
namespace ts {
const brackets = createBracketsMap();
- const syntheticParent: TextRange = { pos: -1, end: -1 };
/*@internal*/
export function isBuildInfoFile(file: string) {
@@ -861,20 +860,11 @@ namespace ts {
return outputFiles;
}
- const enum PipelinePhase {
- Notification,
- Substitution,
- Comments,
- SourceMaps,
- Emit
- }
-
export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer {
const {
hasGlobalName,
- onEmitNode = noEmitNotification,
- isEmitNotificationEnabled,
- substituteNode = noEmitSubstitution,
+ onBeforeEmitNode,
+ onAfterEmitNode,
onBeforeEmitNodeArray,
onAfterEmitNodeArray,
onBeforeEmitToken,
@@ -923,9 +913,9 @@ namespace ts {
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[] | undefined;
let hasWrittenComment = false;
let commentsDisabled = !!printerOptions.removeComments;
- let lastNode: Node | undefined;
- let lastSubstitution: Node | undefined;
const { enter: enterComment, exit: exitComment } = performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment");
+ const preprint = createPreprinter(handlers);
+ const emitBinaryExpression = createEmitBinaryExpression();
reset();
return {
@@ -1003,7 +993,7 @@ namespace ts {
if (sourceFile) {
setSourceFile(sourceFile);
}
- emitList(syntheticParent, nodes, format);
+ emitList(/*parentNode*/ undefined, nodes, format);
reset();
writer = previousWriter;
}
@@ -1147,7 +1137,7 @@ namespace ts {
setSourceFile(sourceFile);
}
- pipelineEmit(hint, node);
+ emit(preprint(hint, node));
}
function setSourceFile(sourceFile: SourceFile | undefined) {
@@ -1179,8 +1169,6 @@ namespace ts {
currentSourceFile = undefined!;
currentLineMap = undefined!;
detachedCommentsInfo = undefined;
- lastNode = undefined;
- lastSubstitution = undefined;
setWriter(/*output*/ undefined, /*_sourceMapGenerator*/ undefined);
}
@@ -1188,678 +1176,681 @@ namespace ts {
return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile!));
}
- function emit(node: Node): Node;
- function emit(node: Node | undefined): Node | undefined;
+ function emit(node: Node): void;
+ function emit(node: Node | undefined): void;
function emit(node: Node | undefined) {
if (node === undefined) return;
-
const prevSourceFileTextKind = recordBundleFileInternalSectionStart(node);
- const substitute = pipelineEmit(EmitHint.Unspecified, node);
+
+ emitWithContext(node, emitWorker);
+
recordBundleFileInternalSectionEnd(prevSourceFileTextKind);
- return substitute;
}
- function emitIdentifierName(node: Identifier): Node;
- function emitIdentifierName(node: Identifier | undefined): Node | undefined;
- function emitIdentifierName(node: Identifier | undefined): Node | undefined {
- if (node === undefined) return;
- return pipelineEmit(EmitHint.IdentifierName, node);
+ function shouldEmitComments(node: Node) {
+ return !commentsDisabled && !isSourceFile(node);
}
- function emitExpression(node: Expression): Node;
- function emitExpression(node: Expression | undefined): Node | undefined;
- function emitExpression(node: Expression | undefined): Node | undefined {
- if (node === undefined) return;
- return pipelineEmit(EmitHint.Expression, node);
+ function shouldEmitSourceMaps(node: Node) {
+ return !sourceMapsDisabled &&
+ !isSourceFile(node) &&
+ !isInJsonFile(node) &&
+ !isUnparsedSource(node) &&
+ !isUnparsedPrepend(node);
}
- function emitJsxAttributeValue(node: StringLiteral | JsxExpression): Node {
- return pipelineEmit(isStringLiteral(node) ? EmitHint.JsxAttributeValue : EmitHint.Unspecified, node);
- }
+ function beforeEmitWithContext(node: Node, shouldEmitComments: boolean, shouldEmitSourceMaps: boolean) {
+ onBeforeEmitNode?.(node);
- function pipelineEmit(emitHint: EmitHint, node: Node) {
- const savedLastNode = lastNode;
- const savedLastSubstitution = lastSubstitution;
- const savedPreserveSourceNewlines = preserveSourceNewlines;
- lastNode = node;
- lastSubstitution = undefined;
- if (preserveSourceNewlines && !!(getEmitFlags(node) & EmitFlags.IgnoreSourceNewlines)) {
+ const emitFlags = getEmitFlags(node);
+ const commentRange = shouldEmitComments ? getCommentRange(node) : undefined;
+ const sourceMapRange = shouldEmitSourceMaps ? getSourceMapRange(node) : undefined;
+
+ if (preserveSourceNewlines && (emitFlags & EmitFlags.IgnoreSourceNewlines)) {
preserveSourceNewlines = false;
}
- const pipelinePhase = getPipelinePhase(PipelinePhase.Notification, emitHint, node);
- pipelinePhase(emitHint, node);
+ // Emit leading comments
+ if (commentRange) {
+ emitLeadingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end);
+ if (emitFlags & EmitFlags.NoNestedComments) {
+ commentsDisabled = true;
+ }
+ }
+
+ // Emit leading sourcemap
+ if (sourceMapRange) {
+ if (isUnparsedNode(node)) {
+ Debug.assertIsDefined(node.parent, "UnparsedNodes must have parent pointers");
+ const parsed = getParsedSourceMap(node.parent);
+ if (parsed && sourceMapGenerator) {
+ sourceMapGenerator.appendSourceMap(
+ writer.getLine(),
+ writer.getColumn(),
+ parsed,
+ node.parent.sourceMapPath!,
+ node.parent.getLineAndCharacterOfPosition(node.pos),
+ node.parent.getLineAndCharacterOfPosition(node.end)
+ );
+ }
+ }
+ else {
+ const source = sourceMapRange.source || sourceMapSource;
+ if (node.kind !== SyntaxKind.NotEmittedStatement
+ && (emitFlags & EmitFlags.NoLeadingSourceMap) === 0
+ && sourceMapRange.pos >= 0) {
+ emitSourcePos(sourceMapRange.source || sourceMapSource, skipSourceTrivia(source, sourceMapRange.pos));
+ }
+ if (emitFlags & EmitFlags.NoNestedSourceMaps) {
+ sourceMapsDisabled = true;
+ }
+ }
+ }
+ }
+
+ function afterEmitWithContext(node: Node, shouldEmitComments: boolean, shouldEmitSourceMaps: boolean, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number, savedPreserveSourceNewlines: boolean | undefined) {
+ const emitFlags = getEmitFlags(node);
+ const commentRange = shouldEmitComments ? getCommentRange(node) : undefined;
+ const sourceMapRange = shouldEmitSourceMaps ? getSourceMapRange(node) : undefined;
+
+ // Emit trailing sourcemap
+ if (sourceMapRange) {
+ if (!isUnparsedNode(node)) {
+ if (emitFlags & EmitFlags.NoNestedSourceMaps) {
+ sourceMapsDisabled = false;
+ }
+ if (node.kind !== SyntaxKind.NotEmittedStatement
+ && (emitFlags & EmitFlags.NoTrailingSourceMap) === 0
+ && sourceMapRange.end >= 0) {
+ emitSourcePos(sourceMapRange.source || sourceMapSource, sourceMapRange.end);
+ }
+ }
+ }
- Debug.assert(lastNode === node);
+ // Emit trailing comments
+ if (commentRange) {
+ if (emitFlags & EmitFlags.NoNestedComments) {
+ commentsDisabled = false;
+ }
+ emitTrailingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd);
+ }
- const substitute = lastSubstitution;
- lastNode = savedLastNode;
- lastSubstitution = savedLastSubstitution;
preserveSourceNewlines = savedPreserveSourceNewlines;
+ onAfterEmitNode?.(node);
+ }
- return substitute || node;
+ function emitWithContext(node: T, emitCallback: (node: T) => void) {
+ const savedPreserveSourceNewlines = preserveSourceNewlines;
+ const savedContainerPos = containerPos;
+ const savedContainerEnd = containerEnd;
+ const savedDeclarationListContainerEnd = declarationListContainerEnd;
+ const emitComments = shouldEmitComments(node);
+ const emitSourceMaps = shouldEmitSourceMaps(node);
+ beforeEmitWithContext(node, emitComments, emitSourceMaps);
+ emitCallback(node);
+ afterEmitWithContext(node, emitComments, emitSourceMaps, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd, savedPreserveSourceNewlines);
}
- function getPipelinePhase(phase: PipelinePhase, emitHint: EmitHint, node: Node) {
- switch (phase) {
- case PipelinePhase.Notification:
- if (onEmitNode !== noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node))) {
- return pipelineEmitWithNotification;
- }
- // falls through
+ function emitWorker(node: Node): void {
+ switch (node.kind) {
+ // Literals
+ case SyntaxKind.NumericLiteral:
+ case SyntaxKind.BigIntLiteral:
+ return emitNumericOrBigIntLiteral(node);
+
+ case SyntaxKind.StringLiteral:
+ case SyntaxKind.RegularExpressionLiteral:
+ case SyntaxKind.NoSubstitutionTemplateLiteral:
+ return emitLiteral(node, /*jsxAttributeEscape*/ false);
+
+ case SyntaxKind.JsxText:
+ return emitJsxText(node);
+
+ // Pseudo-literals
+ case SyntaxKind.TemplateHead:
+ case SyntaxKind.TemplateMiddle:
+ case SyntaxKind.TemplateTail:
+ return emitLiteral(node, /*jsxAttributeEscape*/ false);
+
+ // Identifiers and PrivateIdentifiers
+ case SyntaxKind.Identifier:
+ return emitIdentifier(node);
+ case SyntaxKind.PrivateIdentifier:
+ return emitPrivateIdentifier(node as PrivateIdentifier);
- case PipelinePhase.Substitution:
- if (substituteNode !== noEmitSubstitution && (lastSubstitution = substituteNode(emitHint, node)) !== node) {
- return pipelineEmitWithSubstitution;
- }
- // falls through
+ // Names
+ case SyntaxKind.QualifiedName:
+ return emitQualifiedName(node);
+ case SyntaxKind.ComputedPropertyName:
+ return emitComputedPropertyName(node);
- case PipelinePhase.Comments:
- if (!commentsDisabled && node.kind !== SyntaxKind.SourceFile) {
- return pipelineEmitWithComments;
- }
- // falls through
+ // Signature elements
+ case SyntaxKind.TypeParameter:
+ return emitTypeParameter(node);
+ case SyntaxKind.Parameter:
+ return emitParameter(node);
+ case SyntaxKind.Decorator:
+ return emitDecorator(node);
- case PipelinePhase.SourceMaps:
- if (!sourceMapsDisabled && node.kind !== SyntaxKind.SourceFile && !isInJsonFile(node)) {
- return pipelineEmitWithSourceMap;
- }
- // falls through
+ // Type members
+ case SyntaxKind.PropertySignature:
+ return emitPropertySignature(node);
+ case SyntaxKind.PropertyDeclaration:
+ return emitPropertyDeclaration(node);
+ case SyntaxKind.MethodSignature:
+ return emitMethodSignature(node);
+ case SyntaxKind.MethodDeclaration:
+ return emitMethodDeclaration(node);
+ case SyntaxKind.Constructor:
+ return emitConstructor(node);
+ case SyntaxKind.GetAccessor:
+ case SyntaxKind.SetAccessor:
+ return emitAccessorDeclaration(node);
+ case SyntaxKind.CallSignature:
+ return emitCallSignature(node);
+ case SyntaxKind.ConstructSignature:
+ return emitConstructSignature(node);
+ case SyntaxKind.IndexSignature:
+ return emitIndexSignature(node);
+
+ // Types
+ case SyntaxKind.TypePredicate:
+ return emitTypePredicate(node);
+ case SyntaxKind.TypeReference:
+ return emitTypeReference(node);
+ case SyntaxKind.FunctionType:
+ return emitFunctionType(node);
+ case SyntaxKind.ConstructorType:
+ return emitConstructorType(node);
+ case SyntaxKind.TypeQuery:
+ return emitTypeQuery(node);
+ case SyntaxKind.TypeLiteral:
+ return emitTypeLiteral(node);
+ case SyntaxKind.ArrayType:
+ return emitArrayType(node);
+ case SyntaxKind.TupleType:
+ return emitTupleType(node);
+ case SyntaxKind.OptionalType:
+ return emitOptionalType(node);
+ // SyntaxKind.RestType is handled below
+ case SyntaxKind.UnionType:
+ return emitUnionType(node);
+ case SyntaxKind.IntersectionType:
+ return emitIntersectionType(node);
+ case SyntaxKind.ConditionalType:
+ return emitConditionalType(node);
+ case SyntaxKind.InferType:
+ return emitInferType(node);
+ case SyntaxKind.ParenthesizedType:
+ return emitParenthesizedType(node);
+ case SyntaxKind.ThisType:
+ return emitThisType();
+ case SyntaxKind.TypeOperator:
+ return emitTypeOperator(node);
+ case SyntaxKind.IndexedAccessType:
+ return emitIndexedAccessType(node);
+ case SyntaxKind.MappedType:
+ return emitMappedType(node);
+ case SyntaxKind.LiteralType:
+ return emitLiteralType(node);
+ case SyntaxKind.NamedTupleMember:
+ return emitNamedTupleMember(node as NamedTupleMember);
+ case SyntaxKind.TemplateLiteralType:
+ return emitTemplateType(node);
+ case SyntaxKind.TemplateLiteralTypeSpan:
+ return emitTemplateTypeSpan(node);
+ case SyntaxKind.ImportType:
+ return emitImportTypeNode(node);
+
+ // Binding patterns
+ case SyntaxKind.ObjectBindingPattern:
+ return emitObjectBindingPattern(node);
+ case SyntaxKind.ArrayBindingPattern:
+ return emitArrayBindingPattern(node);
+ case SyntaxKind.BindingElement:
+ return emitBindingElement(node);
+
+ // Expressions
+ case SyntaxKind.ArrayLiteralExpression:
+ return emitArrayLiteralExpression(node);
+ case SyntaxKind.ObjectLiteralExpression:
+ return emitObjectLiteralExpression(node);
+ case SyntaxKind.PropertyAccessExpression:
+ return emitPropertyAccessExpression(node);
+ case SyntaxKind.ElementAccessExpression:
+ return emitElementAccessExpression(node);
+ case SyntaxKind.CallExpression:
+ return emitCallExpression(node);
+ case SyntaxKind.NewExpression:
+ return emitNewExpression(node);
+ case SyntaxKind.TaggedTemplateExpression:
+ return emitTaggedTemplateExpression(node);
+ case SyntaxKind.TypeAssertionExpression:
+ return emitTypeAssertionExpression(node);
+ case SyntaxKind.ParenthesizedExpression:
+ return emitParenthesizedExpression(node);
+ case SyntaxKind.FunctionExpression:
+ return emitFunctionExpression(node);
+ case SyntaxKind.ArrowFunction:
+ return emitArrowFunction(node);
+ case SyntaxKind.DeleteExpression:
+ return emitDeleteExpression(node);
+ case SyntaxKind.TypeOfExpression:
+ return emitTypeOfExpression(node);
+ case SyntaxKind.VoidExpression:
+ return emitVoidExpression(node);
+ case SyntaxKind.AwaitExpression:
+ return emitAwaitExpression(node);
+ case SyntaxKind.PrefixUnaryExpression:
+ return emitPrefixUnaryExpression(node);
+ case SyntaxKind.PostfixUnaryExpression:
+ return emitPostfixUnaryExpression(node);
+ case SyntaxKind.BinaryExpression:
+ return emitBinaryExpression(node);
+ case SyntaxKind.ConditionalExpression:
+ return emitConditionalExpression(node);
+ case SyntaxKind.TemplateExpression:
+ return emitTemplateExpression(node);
+ case SyntaxKind.YieldExpression:
+ return emitYieldExpression(node);
+ case SyntaxKind.SpreadElement:
+ return emitSpreadExpression(node);
+ case SyntaxKind.ClassExpression:
+ return emitClassExpression(node);
+ case SyntaxKind.OmittedExpression:
+ return;
+ case SyntaxKind.ExpressionWithTypeArguments:
+ return emitExpressionWithTypeArguments(node);
+ case SyntaxKind.AsExpression:
+ return emitAsExpression(node);
+ case SyntaxKind.NonNullExpression:
+ return emitNonNullExpression(node);
+ case SyntaxKind.MetaProperty:
+ return emitMetaProperty(node);
+ case SyntaxKind.SyntheticExpression:
+ Debug.fail("SyntheticExpression should never be printed.");
+ break;
- case PipelinePhase.Emit:
- return pipelineEmitWithHint;
+ // Misc
+ case SyntaxKind.TemplateSpan:
+ return emitTemplateSpan(node);
+ case SyntaxKind.SemicolonClassElement:
+ return emitSemicolonClassElement();
- default:
- return Debug.assertNever(phase);
+ // Element
+ case SyntaxKind.Block:
+ return emitBlock(node);
+ case SyntaxKind.EmptyStatement:
+ return emitEmptyStatement(/*isEmbeddedStatement*/ false);
+ case SyntaxKind.VariableStatement:
+ return emitVariableStatement(node);
+ case SyntaxKind.ExpressionStatement:
+ return emitExpressionStatement(node);
+ case SyntaxKind.IfStatement:
+ return emitIfStatement(node);
+ case SyntaxKind.DoStatement:
+ return emitDoStatement(node);
+ case SyntaxKind.WhileStatement:
+ return emitWhileStatement(node);
+ case SyntaxKind.ForStatement:
+ return emitForStatement(node);
+ case SyntaxKind.ForInStatement:
+ return emitForInStatement(node);
+ case SyntaxKind.ForOfStatement:
+ return emitForOfStatement(node);
+ case SyntaxKind.ContinueStatement:
+ return emitContinueStatement(node);
+ case SyntaxKind.BreakStatement:
+ return emitBreakStatement(node);
+ case SyntaxKind.ReturnStatement:
+ return emitReturnStatement(node);
+ case SyntaxKind.WithStatement:
+ return emitWithStatement(node);
+ case SyntaxKind.SwitchStatement:
+ return emitSwitchStatement(node);
+ case SyntaxKind.LabeledStatement:
+ return emitLabeledStatement(node);
+ case SyntaxKind.ThrowStatement:
+ return emitThrowStatement(node);
+ case SyntaxKind.TryStatement:
+ return emitTryStatement(node);
+ case SyntaxKind.DebuggerStatement:
+ return emitDebuggerStatement(node);
+
+ // Declarations
+ case SyntaxKind.VariableDeclaration:
+ return emitVariableDeclaration(node);
+ case SyntaxKind.VariableDeclarationList:
+ return emitVariableDeclarationList(node);
+ case SyntaxKind.FunctionDeclaration:
+ return emitFunctionDeclaration(node);
+ case SyntaxKind.ClassDeclaration:
+ return emitClassDeclaration(node);
+ case SyntaxKind.InterfaceDeclaration:
+ return emitInterfaceDeclaration(node);
+ case SyntaxKind.TypeAliasDeclaration:
+ return emitTypeAliasDeclaration(node);
+ case SyntaxKind.EnumDeclaration:
+ return emitEnumDeclaration(node);
+ case SyntaxKind.ModuleDeclaration:
+ return emitModuleDeclaration(node);
+ case SyntaxKind.ModuleBlock:
+ return emitModuleBlock(node);
+ case SyntaxKind.CaseBlock:
+ return emitCaseBlock(node);
+ case SyntaxKind.NamespaceExportDeclaration:
+ return emitNamespaceExportDeclaration(node);
+ case SyntaxKind.ImportEqualsDeclaration:
+ return emitImportEqualsDeclaration(node);
+ case SyntaxKind.ImportDeclaration:
+ return emitImportDeclaration(node);
+ case SyntaxKind.ImportClause:
+ return emitImportClause(node);
+ case SyntaxKind.NamespaceImport:
+ return emitNamespaceImport(node);
+ case SyntaxKind.NamedImports:
+ return emitNamedImports(node);
+ case SyntaxKind.ImportSpecifier:
+ return emitImportSpecifier(node);
+ case SyntaxKind.ExportAssignment:
+ return emitExportAssignment(node);
+ case SyntaxKind.ExportDeclaration:
+ return emitExportDeclaration(node);
+ case SyntaxKind.NamedExports:
+ return emitNamedExports(node);
+ case SyntaxKind.NamespaceExport:
+ return emitNamespaceExport(node);
+ case SyntaxKind.ExportSpecifier:
+ return emitExportSpecifier(node);
+ case SyntaxKind.MissingDeclaration:
+ return;
+
+ // Module references
+ case SyntaxKind.ExternalModuleReference:
+ return emitExternalModuleReference(node);
+
+ // JSX
+ case SyntaxKind.JsxElement:
+ return emitJsxElement(node);
+ case SyntaxKind.JsxSelfClosingElement:
+ return emitJsxSelfClosingElement(node);
+ case SyntaxKind.JsxFragment:
+ return emitJsxFragment(node);
+ case SyntaxKind.JsxOpeningElement:
+ case SyntaxKind.JsxOpeningFragment:
+ return emitJsxOpeningElementOrFragment(node);
+ case SyntaxKind.JsxClosingElement:
+ case SyntaxKind.JsxClosingFragment:
+ return emitJsxClosingElementOrFragment(node);
+ case SyntaxKind.JsxAttribute:
+ return emitJsxAttribute(node);
+ case SyntaxKind.JsxAttributes:
+ return emitJsxAttributes(node);
+ case SyntaxKind.JsxSpreadAttribute:
+ return emitJsxSpreadAttribute(node);
+ case SyntaxKind.JsxExpression:
+ return emitJsxExpression(node);
+
+ // Clauses
+ case SyntaxKind.CaseClause:
+ return emitCaseClause(node);
+ case SyntaxKind.DefaultClause:
+ return emitDefaultClause(node);
+ case SyntaxKind.HeritageClause:
+ return emitHeritageClause(node);
+ case SyntaxKind.CatchClause:
+ return emitCatchClause(node);
+
+ // Property assignments
+ case SyntaxKind.PropertyAssignment:
+ return emitPropertyAssignment(node);
+ case SyntaxKind.ShorthandPropertyAssignment:
+ return emitShorthandPropertyAssignment(node);
+ case SyntaxKind.SpreadAssignment:
+ return emitSpreadAssignment(node as SpreadAssignment);
+
+ // Enum
+ case SyntaxKind.EnumMember:
+ return emitEnumMember(node);
+
+ // Unparsed
+ case SyntaxKind.UnparsedPrologue:
+ return writeUnparsedNode(node);
+ case SyntaxKind.UnparsedSource:
+ case SyntaxKind.UnparsedPrepend:
+ return emitUnparsedSourceOrPrepend(node);
+ case SyntaxKind.UnparsedText:
+ case SyntaxKind.UnparsedInternalText:
+ return emitUnparsedTextLike(node);
+ case SyntaxKind.UnparsedSyntheticReference:
+ return emitUnparsedSyntheticReference(node);
+
+ // Top-level nodes
+ case SyntaxKind.SourceFile:
+ return emitSourceFile(node);
+ case SyntaxKind.Bundle:
+ Debug.fail("Bundles should be printed using printBundle");
+ break;
+ // SyntaxKind.UnparsedSource (handled above)
+ case SyntaxKind.InputFiles:
+ Debug.fail("InputFiles should not be printed");
+ break;
+
+ // JSDoc nodes (only used in codefixes currently)
+ case SyntaxKind.JSDocTypeExpression:
+ return emitJSDocTypeExpression(node as JSDocTypeExpression);
+ case SyntaxKind.JSDocNameReference:
+ return emitJSDocNameReference(node as JSDocNameReference);
+ case SyntaxKind.JSDocAllType:
+ return writePunctuation("*");
+ case SyntaxKind.JSDocUnknownType:
+ return writePunctuation("?");
+ case SyntaxKind.JSDocNullableType:
+ return emitJSDocNullableType(node as JSDocNullableType);
+ case SyntaxKind.JSDocNonNullableType:
+ return emitJSDocNonNullableType(node as JSDocNonNullableType);
+ case SyntaxKind.JSDocOptionalType:
+ return emitJSDocOptionalType(node as JSDocOptionalType);
+ case SyntaxKind.JSDocFunctionType:
+ return emitJSDocFunctionType(node as JSDocFunctionType);
+ case SyntaxKind.RestType:
+ case SyntaxKind.JSDocVariadicType:
+ return emitRestOrJSDocVariadicType(node as RestTypeNode | JSDocVariadicType);
+ // SyntaxKind.JSDocNamepathType (missing)
+ case SyntaxKind.JSDocComment:
+ return emitJSDoc(node as JSDoc);
+ case SyntaxKind.JSDocTypeLiteral:
+ return emitJSDocTypeLiteral(node as JSDocTypeLiteral);
+ case SyntaxKind.JSDocSignature:
+ return emitJSDocSignature(node as JSDocSignature);
+ case SyntaxKind.JSDocTag:
+ case SyntaxKind.JSDocClassTag:
+ return emitJSDocSimpleTag(node as JSDocTag);
+ case SyntaxKind.JSDocAugmentsTag:
+ case SyntaxKind.JSDocImplementsTag:
+ return emitJSDocHeritageTag(node as JSDocImplementsTag | JSDocAugmentsTag);
+ // SyntaxKind.JSDocAuthorTag (missing)
+ // SyntaxKind.JSDocDeprecatedTag (missing)
+ // SyntaxKind.JSDocClassTag (see JSDocTag, above)
+ // SyntaxKind.JSDocPublicTag (missing)
+ // SyntaxKind.JSDocPrivateTag (missing)
+ // SyntaxKind.JSDocProtectedTag (missing)
+ // SyntaxKind.JSDocReadonlyTag (missing)
+ case SyntaxKind.JSDocCallbackTag:
+ return emitJSDocCallbackTag(node as JSDocCallbackTag);
+ // SyntaxKind.JSDocEnumTag (see below)
+ case SyntaxKind.JSDocParameterTag:
+ case SyntaxKind.JSDocPropertyTag:
+ return emitJSDocPropertyLikeTag(node as JSDocPropertyLikeTag);
+ case SyntaxKind.JSDocEnumTag:
+ case SyntaxKind.JSDocReturnTag:
+ case SyntaxKind.JSDocThisTag:
+ case SyntaxKind.JSDocTypeTag:
+ return emitJSDocSimpleTypedTag(node as JSDocTypeTag);
+ case SyntaxKind.JSDocTemplateTag:
+ return emitJSDocTemplateTag(node as JSDocTemplateTag);
+ case SyntaxKind.JSDocTypedefTag:
+ return emitJSDocTypedefTag(node as JSDocTypedefTag);
+ case SyntaxKind.JSDocSeeTag:
+ return emitJSDocSeeTag(node as JSDocSeeTag);
+ // SyntaxKind.JSDocPropertyTag (see JSDocParameterTag, above)
+
+ // Synthesized list
+ case SyntaxKind.SyntaxList:
+ Debug.fail("SyntaxList should not be printed");
+ break;
+
+ // Transformation nodes
+ case SyntaxKind.NotEmittedStatement:
+ break;
+ case SyntaxKind.PartiallyEmittedExpression:
+ return emitPartiallyEmittedExpression(node);
+ case SyntaxKind.CommaListExpression:
+ return emitCommaList(node);
+ case SyntaxKind.MergeDeclarationMarker:
+ case SyntaxKind.EndOfDeclarationMarker:
+ break;
+ case SyntaxKind.SyntheticReferenceExpression:
+ Debug.fail("SyntheticReferenceExpression should not be printed");
}
+ if (isKeyword(node.kind)) return writeTokenNode(node, writeKeyword);
+ if (isTokenKind(node.kind)) return writeTokenNode(node, writePunctuation);
}
- function getNextPipelinePhase(currentPhase: PipelinePhase, emitHint: EmitHint, node: Node) {
- return getPipelinePhase(currentPhase + 1, emitHint, node);
+ function emitMappedTypeParameter(node: TypeParameterDeclaration): void {
+ emit(node.name);
+ writeSpace();
+ writeKeyword("in");
+ writeSpace();
+ emit(node.constraint);
}
- function pipelineEmitWithNotification(hint: EmitHint, node: Node) {
- Debug.assert(lastNode === node);
- const pipelinePhase = getNextPipelinePhase(PipelinePhase.Notification, hint, node);
- onEmitNode(hint, node, pipelinePhase);
- Debug.assert(lastNode === node);
+ function getHelpersFromBundledSourceFiles(bundle: Bundle): string[] | undefined {
+ let result: string[] | undefined;
+ if (moduleKind === ModuleKind.None || printerOptions.noEmitHelpers) {
+ return undefined;
+ }
+ const bundledHelpers = new Map();
+ for (const sourceFile of bundle.sourceFiles) {
+ const shouldSkip = getExternalHelpersModuleName(sourceFile) !== undefined;
+ const helpers = getSortedEmitHelpers(sourceFile);
+ if (!helpers) continue;
+ for (const helper of helpers) {
+ if (!helper.scoped && !shouldSkip && !bundledHelpers.get(helper.name)) {
+ bundledHelpers.set(helper.name, true);
+ (result || (result = [])).push(helper.name);
+ }
+ }
+ }
+
+ return result;
}
- function pipelineEmitWithHint(hint: EmitHint, node: Node): void {
- Debug.assert(lastNode === node || lastSubstitution === node);
- if (hint === EmitHint.SourceFile) return emitSourceFile(cast(node, isSourceFile));
- if (hint === EmitHint.IdentifierName) return emitIdentifier(cast(node, isIdentifier));
- if (hint === EmitHint.JsxAttributeValue) return emitLiteral(cast(node, isStringLiteral), /*jsxAttributeEscape*/ true);
- if (hint === EmitHint.MappedTypeParameter) return emitMappedTypeParameter(cast(node, isTypeParameterDeclaration));
- if (hint === EmitHint.EmbeddedStatement) {
- Debug.assertNode(node, isEmptyStatement);
- return emitEmptyStatement(/*isEmbeddedStatement*/ true);
+ function emitHelpers(node: Node) {
+ let helpersEmitted = false;
+ const bundle = node.kind === SyntaxKind.Bundle ? node : undefined;
+ if (bundle && moduleKind === ModuleKind.None) {
+ return;
}
- if (hint === EmitHint.Unspecified) {
- if (isKeyword(node.kind)) return writeTokenNode(node, writeKeyword);
-
- switch (node.kind) {
- // Pseudo-literals
- case SyntaxKind.TemplateHead:
- case SyntaxKind.TemplateMiddle:
- case SyntaxKind.TemplateTail:
- return emitLiteral(node, /*jsxAttributeEscape*/ false);
+ const numPrepends = bundle ? bundle.prepends.length : 0;
+ const numNodes = bundle ? bundle.sourceFiles.length + numPrepends : 1;
+ for (let i = 0; i < numNodes; i++) {
+ const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node;
+ const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile!;
+ const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile));
+ const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit;
+ const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode);
+ if (helpers) {
+ for (const helper of helpers) {
+ if (!helper.scoped) {
+ // Skip the helper if it can be skipped and the noEmitHelpers compiler
+ // option is set, or if it can be imported and the importHelpers compiler
+ // option is set.
+ if (shouldSkip) continue;
- case SyntaxKind.UnparsedSource:
- case SyntaxKind.UnparsedPrepend:
- return emitUnparsedSourceOrPrepend(node);
+ // Skip the helper if it can be bundled but hasn't already been emitted and we
+ // are emitting a bundled module.
+ if (shouldBundle) {
+ if (bundledHelpers.get(helper.name)) {
+ continue;
+ }
- case SyntaxKind.UnparsedPrologue:
- return writeUnparsedNode(node);
+ bundledHelpers.set(helper.name, true);
+ }
+ }
+ else if (bundle) {
+ // Skip the helper if it is scoped and we are emitting bundled helpers
+ continue;
+ }
+ const pos = getTextPosWithWriteLine();
+ if (typeof helper.text === "string") {
+ writeLines(helper.text);
+ }
+ else {
+ writeLines(helper.text(makeFileLevelOptimisticUniqueName));
+ }
+ if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.EmitHelpers, data: helper.name });
+ helpersEmitted = true;
+ }
+ }
+ }
- case SyntaxKind.UnparsedText:
- case SyntaxKind.UnparsedInternalText:
- return emitUnparsedTextLike(node);
+ return helpersEmitted;
+ }
- case SyntaxKind.UnparsedSyntheticReference:
- return emitUnparsedSyntheticReference(node);
+ function getSortedEmitHelpers(node: Node) {
+ const helpers = getEmitHelpers(node);
+ return helpers && stableSort(helpers, compareEmitHelpers);
+ }
+ //
+ // Literals/Pseudo-literals
+ //
- // Identifiers
- case SyntaxKind.Identifier:
- return emitIdentifier(node);
+ // SyntaxKind.NumericLiteral
+ // SyntaxKind.BigIntLiteral
+ function emitNumericOrBigIntLiteral(node: NumericLiteral | BigIntLiteral) {
+ emitLiteral(node, /*jsxAttributeEscape*/ false);
+ }
- // PrivateIdentifiers
- case SyntaxKind.PrivateIdentifier:
- return emitPrivateIdentifier(node as PrivateIdentifier);
+ // SyntaxKind.StringLiteral
+ // SyntaxKind.RegularExpressionLiteral
+ // SyntaxKind.NoSubstitutionTemplateLiteral
+ // SyntaxKind.TemplateHead
+ // SyntaxKind.TemplateMiddle
+ // SyntaxKind.TemplateTail
+ function emitLiteral(node: LiteralLikeNode, jsxAttributeEscape: boolean) {
+ const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape, jsxAttributeEscape);
+ if ((printerOptions.sourceMap || printerOptions.inlineSourceMap)
+ && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
+ writeLiteral(text);
+ }
+ else {
+ // Quick info expects all literals to be called with writeStringLiteral, as there's no specific type for numberLiterals
+ writeStringLiteral(text);
+ }
+ }
- // Parse tree nodes
- // Names
- case SyntaxKind.QualifiedName:
- return emitQualifiedName(node);
- case SyntaxKind.ComputedPropertyName:
- return emitComputedPropertyName(node);
+ function emitStringLiteralWithJsxAttributeEscape(node: StringLiteral) {
+ emitLiteral(node, /*jsxAttributeEscape*/ true);
+ }
- // Signature elements
- case SyntaxKind.TypeParameter:
- return emitTypeParameter(node);
- case SyntaxKind.Parameter:
- return emitParameter(node);
- case SyntaxKind.Decorator:
- return emitDecorator(node);
+ // SyntaxKind.UnparsedSource
+ // SyntaxKind.UnparsedPrepend
+ function emitUnparsedSourceOrPrepend(unparsed: UnparsedSource | UnparsedPrepend) {
+ for (const text of unparsed.texts) {
+ writeLine();
+ emit(text);
+ }
+ }
- // Type members
- case SyntaxKind.PropertySignature:
- return emitPropertySignature(node);
- case SyntaxKind.PropertyDeclaration:
- return emitPropertyDeclaration(node);
- case SyntaxKind.MethodSignature:
- return emitMethodSignature(node);
- case SyntaxKind.MethodDeclaration:
- return emitMethodDeclaration(node);
- case SyntaxKind.Constructor:
- return emitConstructor(node);
- case SyntaxKind.GetAccessor:
- case SyntaxKind.SetAccessor:
- return emitAccessorDeclaration(node);
- case SyntaxKind.CallSignature:
- return emitCallSignature(node);
- case SyntaxKind.ConstructSignature:
- return emitConstructSignature(node);
- case SyntaxKind.IndexSignature:
- return emitIndexSignature(node);
- case SyntaxKind.TemplateLiteralTypeSpan:
- return emitTemplateTypeSpan(node);
-
- // Types
- case SyntaxKind.TypePredicate:
- return emitTypePredicate(node);
- case SyntaxKind.TypeReference:
- return emitTypeReference(node);
- case SyntaxKind.FunctionType:
- return emitFunctionType(node);
- case SyntaxKind.JSDocFunctionType:
- return emitJSDocFunctionType(node as JSDocFunctionType);
- case SyntaxKind.ConstructorType:
- return emitConstructorType(node);
- case SyntaxKind.TypeQuery:
- return emitTypeQuery(node);
- case SyntaxKind.TypeLiteral:
- return emitTypeLiteral(node);
- case SyntaxKind.ArrayType:
- return emitArrayType(node);
- case SyntaxKind.TupleType:
- return emitTupleType(node);
- case SyntaxKind.OptionalType:
- return emitOptionalType(node);
- case SyntaxKind.UnionType:
- return emitUnionType(node);
- case SyntaxKind.IntersectionType:
- return emitIntersectionType(node);
- case SyntaxKind.ConditionalType:
- return emitConditionalType(node);
- case SyntaxKind.InferType:
- return emitInferType(node);
- case SyntaxKind.ParenthesizedType:
- return emitParenthesizedType(node);
- case SyntaxKind.ExpressionWithTypeArguments:
- return emitExpressionWithTypeArguments(node);
- case SyntaxKind.ThisType:
- return emitThisType();
- case SyntaxKind.TypeOperator:
- return emitTypeOperator(node);
- case SyntaxKind.IndexedAccessType:
- return emitIndexedAccessType(node);
- case SyntaxKind.MappedType:
- return emitMappedType(node);
- case SyntaxKind.LiteralType:
- return emitLiteralType(node);
- case SyntaxKind.TemplateLiteralType:
- return emitTemplateType(node);
- case SyntaxKind.ImportType:
- return emitImportTypeNode(node);
- case SyntaxKind.JSDocAllType:
- writePunctuation("*");
- return;
- case SyntaxKind.JSDocUnknownType:
- writePunctuation("?");
- return;
- case SyntaxKind.JSDocNullableType:
- return emitJSDocNullableType(node as JSDocNullableType);
- case SyntaxKind.JSDocNonNullableType:
- return emitJSDocNonNullableType(node as JSDocNonNullableType);
- case SyntaxKind.JSDocOptionalType:
- return emitJSDocOptionalType(node as JSDocOptionalType);
- case SyntaxKind.RestType:
- case SyntaxKind.JSDocVariadicType:
- return emitRestOrJSDocVariadicType(node as RestTypeNode | JSDocVariadicType);
- case SyntaxKind.NamedTupleMember:
- return emitNamedTupleMember(node as NamedTupleMember);
-
- // Binding patterns
- case SyntaxKind.ObjectBindingPattern:
- return emitObjectBindingPattern(node);
- case SyntaxKind.ArrayBindingPattern:
- return emitArrayBindingPattern(node);
- case SyntaxKind.BindingElement:
- return emitBindingElement(node);
-
- // Misc
- case SyntaxKind.TemplateSpan:
- return emitTemplateSpan(node);
- case SyntaxKind.SemicolonClassElement:
- return emitSemicolonClassElement();
-
- // Statements
- case SyntaxKind.Block:
- return emitBlock(node);
- case SyntaxKind.VariableStatement:
- return emitVariableStatement(node);
- case SyntaxKind.EmptyStatement:
- return emitEmptyStatement(/*isEmbeddedStatement*/ false);
- case SyntaxKind.ExpressionStatement:
- return emitExpressionStatement(node);
- case SyntaxKind.IfStatement:
- return emitIfStatement(node);
- case SyntaxKind.DoStatement:
- return emitDoStatement(node);
- case SyntaxKind.WhileStatement:
- return emitWhileStatement(node);
- case SyntaxKind.ForStatement:
- return emitForStatement(node);
- case SyntaxKind.ForInStatement:
- return emitForInStatement(node);
- case SyntaxKind.ForOfStatement:
- return emitForOfStatement(node);
- case SyntaxKind.ContinueStatement:
- return emitContinueStatement(node);
- case SyntaxKind.BreakStatement:
- return emitBreakStatement(node);
- case SyntaxKind.ReturnStatement:
- return emitReturnStatement(node);
- case SyntaxKind.WithStatement:
- return emitWithStatement(node);
- case SyntaxKind.SwitchStatement:
- return emitSwitchStatement(node);
- case SyntaxKind.LabeledStatement:
- return emitLabeledStatement(node);
- case SyntaxKind.ThrowStatement:
- return emitThrowStatement(node);
- case SyntaxKind.TryStatement:
- return emitTryStatement(node);
- case SyntaxKind.DebuggerStatement:
- return emitDebuggerStatement(node);
-
- // Declarations
- case SyntaxKind.VariableDeclaration:
- return emitVariableDeclaration(node);
- case SyntaxKind.VariableDeclarationList:
- return emitVariableDeclarationList(node);
- case SyntaxKind.FunctionDeclaration:
- return emitFunctionDeclaration(node);
- case SyntaxKind.ClassDeclaration:
- return emitClassDeclaration(node);
- case SyntaxKind.InterfaceDeclaration:
- return emitInterfaceDeclaration(node);
- case SyntaxKind.TypeAliasDeclaration:
- return emitTypeAliasDeclaration(node);
- case SyntaxKind.EnumDeclaration:
- return emitEnumDeclaration(node);
- case SyntaxKind.ModuleDeclaration:
- return emitModuleDeclaration(node);
- case SyntaxKind.ModuleBlock:
- return emitModuleBlock(node);
- case SyntaxKind.CaseBlock:
- return emitCaseBlock(node);
- case SyntaxKind.NamespaceExportDeclaration:
- return emitNamespaceExportDeclaration(node);
- case SyntaxKind.ImportEqualsDeclaration:
- return emitImportEqualsDeclaration(node);
- case SyntaxKind.ImportDeclaration:
- return emitImportDeclaration(node);
- case SyntaxKind.ImportClause:
- return emitImportClause(node);
- case SyntaxKind.NamespaceImport:
- return emitNamespaceImport(node);
- case SyntaxKind.NamespaceExport:
- return emitNamespaceExport(node);
- case SyntaxKind.NamedImports:
- return emitNamedImports(node);
- case SyntaxKind.ImportSpecifier:
- return emitImportSpecifier(node);
- case SyntaxKind.ExportAssignment:
- return emitExportAssignment(node);
- case SyntaxKind.ExportDeclaration:
- return emitExportDeclaration(node);
- case SyntaxKind.NamedExports:
- return emitNamedExports(node);
- case SyntaxKind.ExportSpecifier:
- return emitExportSpecifier(node);
- case SyntaxKind.MissingDeclaration:
- return;
-
- // Module references
- case SyntaxKind.ExternalModuleReference:
- return emitExternalModuleReference(node);
-
- // JSX (non-expression)
- case SyntaxKind.JsxText:
- return emitJsxText(node);
- case SyntaxKind.JsxOpeningElement:
- case SyntaxKind.JsxOpeningFragment:
- return emitJsxOpeningElementOrFragment(node);
- case SyntaxKind.JsxClosingElement:
- case SyntaxKind.JsxClosingFragment:
- return emitJsxClosingElementOrFragment(node);
- case SyntaxKind.JsxAttribute:
- return emitJsxAttribute(node);
- case SyntaxKind.JsxAttributes:
- return emitJsxAttributes(node);
- case SyntaxKind.JsxSpreadAttribute:
- return emitJsxSpreadAttribute(node);
- case SyntaxKind.JsxExpression:
- return emitJsxExpression(node);
-
- // Clauses
- case SyntaxKind.CaseClause:
- return emitCaseClause(node);
- case SyntaxKind.DefaultClause:
- return emitDefaultClause(node);
- case SyntaxKind.HeritageClause:
- return emitHeritageClause(node);
- case SyntaxKind.CatchClause:
- return emitCatchClause(node);
-
- // Property assignments
- case SyntaxKind.PropertyAssignment:
- return emitPropertyAssignment(node);
- case SyntaxKind.ShorthandPropertyAssignment:
- return emitShorthandPropertyAssignment(node);
- case SyntaxKind.SpreadAssignment:
- return emitSpreadAssignment(node as SpreadAssignment);
-
- // Enum
- case SyntaxKind.EnumMember:
- return emitEnumMember(node);
-
- // JSDoc nodes (only used in codefixes currently)
- case SyntaxKind.JSDocParameterTag:
- case SyntaxKind.JSDocPropertyTag:
- return emitJSDocPropertyLikeTag(node as JSDocPropertyLikeTag);
- case SyntaxKind.JSDocReturnTag:
- case SyntaxKind.JSDocTypeTag:
- case SyntaxKind.JSDocThisTag:
- case SyntaxKind.JSDocEnumTag:
- return emitJSDocSimpleTypedTag(node as JSDocTypeTag);
- case SyntaxKind.JSDocImplementsTag:
- case SyntaxKind.JSDocAugmentsTag:
- return emitJSDocHeritageTag(node as JSDocImplementsTag | JSDocAugmentsTag);
- case SyntaxKind.JSDocTemplateTag:
- return emitJSDocTemplateTag(node as JSDocTemplateTag);
- case SyntaxKind.JSDocTypedefTag:
- return emitJSDocTypedefTag(node as JSDocTypedefTag);
- case SyntaxKind.JSDocCallbackTag:
- return emitJSDocCallbackTag(node as JSDocCallbackTag);
- case SyntaxKind.JSDocSignature:
- return emitJSDocSignature(node as JSDocSignature);
- case SyntaxKind.JSDocTypeLiteral:
- return emitJSDocTypeLiteral(node as JSDocTypeLiteral);
- case SyntaxKind.JSDocClassTag:
- case SyntaxKind.JSDocTag:
- return emitJSDocSimpleTag(node as JSDocTag);
- case SyntaxKind.JSDocSeeTag:
- return emitJSDocSeeTag(node as JSDocSeeTag);
- case SyntaxKind.JSDocNameReference:
- return emitJSDocNameReference(node as JSDocNameReference);
-
- case SyntaxKind.JSDocComment:
- return emitJSDoc(node as JSDoc);
-
- // Transformation nodes (ignored)
- }
-
- if (isExpression(node)) {
- hint = EmitHint.Expression;
- if (substituteNode !== noEmitSubstitution) {
- lastSubstitution = node = substituteNode(hint, node);
- }
- }
- else if (isToken(node)) {
- return writeTokenNode(node, writePunctuation);
- }
- }
- if (hint === EmitHint.Expression) {
- switch (node.kind) {
- // Literals
- case SyntaxKind.NumericLiteral:
- case SyntaxKind.BigIntLiteral:
- return emitNumericOrBigIntLiteral(node);
-
- case SyntaxKind.StringLiteral:
- case SyntaxKind.RegularExpressionLiteral:
- case SyntaxKind.NoSubstitutionTemplateLiteral:
- return emitLiteral(node, /*jsxAttributeEscape*/ false);
-
- // Identifiers
- case SyntaxKind.Identifier:
- return emitIdentifier(node);
-
- // Reserved words
- case SyntaxKind.FalseKeyword:
- case SyntaxKind.NullKeyword:
- case SyntaxKind.SuperKeyword:
- case SyntaxKind.TrueKeyword:
- case SyntaxKind.ThisKeyword:
- case SyntaxKind.ImportKeyword:
- writeTokenNode(node, writeKeyword);
- return;
-
- // Expressions
- case SyntaxKind.ArrayLiteralExpression:
- return emitArrayLiteralExpression(node);
- case SyntaxKind.ObjectLiteralExpression:
- return emitObjectLiteralExpression(node);
- case SyntaxKind.PropertyAccessExpression:
- return emitPropertyAccessExpression(node);
- case SyntaxKind.ElementAccessExpression:
- return emitElementAccessExpression(node);
- case SyntaxKind.CallExpression:
- return emitCallExpression(node);
- case SyntaxKind.NewExpression:
- return emitNewExpression(node);
- case SyntaxKind.TaggedTemplateExpression:
- return emitTaggedTemplateExpression(node);
- case SyntaxKind.TypeAssertionExpression:
- return emitTypeAssertionExpression(node);
- case SyntaxKind.ParenthesizedExpression:
- return emitParenthesizedExpression(node);
- case SyntaxKind.FunctionExpression:
- return emitFunctionExpression(