mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Adds ES6 transformer
This commit is contained in:
@@ -238,6 +238,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
|
||||
}
|
||||
|
||||
var useDebugMode = true;
|
||||
var useTransforms = process.env.USE_TRANSFORMS || false;
|
||||
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
|
||||
var compilerFilename = "tsc.js";
|
||||
var LKGCompiler = path.join(LKGDirectory, compilerFilename);
|
||||
@@ -297,6 +298,10 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu
|
||||
options += " --stripInternal"
|
||||
}
|
||||
|
||||
if (useBuiltCompiler && useTransforms) {
|
||||
options += " --experimentalTransforms"
|
||||
}
|
||||
|
||||
var cmd = host + " " + compilerPath + " " + options + " ";
|
||||
cmd = cmd + sources.join(" ");
|
||||
console.log(cmd + "\n");
|
||||
@@ -420,6 +425,10 @@ task("setDebugMode", function() {
|
||||
useDebugMode = true;
|
||||
});
|
||||
|
||||
task("setTransforms", function() {
|
||||
useTransforms = true;
|
||||
});
|
||||
|
||||
task("configure-nightly", [configureNightlyJs], function() {
|
||||
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
|
||||
console.log(cmd);
|
||||
|
||||
+21
-15
@@ -1971,20 +1971,6 @@ namespace ts {
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
if (nodeIsSynthesized(node)) {
|
||||
const expression = (<ExpressionStatement>node).expression;
|
||||
if (nodeIsSynthesized(expression)
|
||||
&& isCallExpression(expression)
|
||||
&& expression.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// A synthesized call to `super` should be transformed to a cleaner emit
|
||||
// when transpiling to ES5/3.
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (isDestructuringAssignment(node)) {
|
||||
// Destructuring assignments are ES6 syntax.
|
||||
@@ -2093,7 +2079,7 @@ namespace ts {
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
// If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax.
|
||||
if (node.flags & NodeFlags.BlockScoped) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBlockScopedBinding;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2106,6 +2092,26 @@ namespace ts {
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.LabeledStatement:
|
||||
// A labeled statement containing a block scoped binding *may* need to be transformed from ES6.
|
||||
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding
|
||||
&& isIterationStatement(this, /*lookInLabeledStatements*/ true)) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
// A loop containing a block scoped binding *may* need to be transformed from ES6.
|
||||
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
// A ClassDeclarations or ClassExpression is ES6 syntax.
|
||||
|
||||
@@ -16672,11 +16672,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Modifiers are never allowed on properties except for 'async' on a method declaration
|
||||
forEach(prop.modifiers, mod => {
|
||||
if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) {
|
||||
grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
|
||||
if (prop.modifiers) {
|
||||
for (const mod of prop.modifiers) {
|
||||
if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) {
|
||||
grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ECMA-262 11.1.5 Object Initialiser
|
||||
// If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
|
||||
|
||||
@@ -320,6 +320,11 @@ namespace ts {
|
||||
name: "allowSyntheticDefaultImports",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking
|
||||
},
|
||||
{
|
||||
name: "experimentalTransforms",
|
||||
type: "boolean",
|
||||
experimental: true
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
+88
-54
@@ -5,11 +5,15 @@ namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
getLeadingCommentsToEmit(node: TextRange): CommentRange[];
|
||||
getTrailingCommentsToEmit(node: TextRange): CommentRange[];
|
||||
emitDetachedComments(node: TextRange): void;
|
||||
emitLeadingComments(node: TextRange, comments?: CommentRange[]): void;
|
||||
emitTrailingComments(node: TextRange, comments?: CommentRange[]): void;
|
||||
getLeadingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
|
||||
getLeadingComments(range: TextRange): CommentRange[];
|
||||
getLeadingCommentsOfPosition(pos: number): CommentRange[];
|
||||
getTrailingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
|
||||
getTrailingComments(range: TextRange): CommentRange[];
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[];
|
||||
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void;
|
||||
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void;
|
||||
emitDetachedComments(range: TextRange): void;
|
||||
}
|
||||
|
||||
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
|
||||
@@ -25,8 +29,8 @@ namespace ts {
|
||||
// This maps start->end for a comment range. See `hasConsumedCommentRange` and
|
||||
// `consumeCommentRange` for usage.
|
||||
let consumedCommentRanges: number[];
|
||||
let leadingCommentRangeNodeStarts: boolean[];
|
||||
let trailingCommentRangeNodeEnds: boolean[];
|
||||
let leadingCommentRangePositions: boolean[];
|
||||
let trailingCommentRangePositions: boolean[];
|
||||
|
||||
return compilerOptions.removeComments
|
||||
? createCommentRemovingWriter()
|
||||
@@ -36,11 +40,13 @@ namespace ts {
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingCommentsToEmit(node: TextRange): CommentRange[] { return undefined; },
|
||||
getTrailingCommentsToEmit(node: TextRange): CommentRange[] { return undefined; },
|
||||
getLeadingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
|
||||
getLeadingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
|
||||
getTrailingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
|
||||
getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
|
||||
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void { },
|
||||
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void { },
|
||||
emitDetachedComments,
|
||||
emitLeadingComments(node: TextRange, comments?: CommentRange[]): void { },
|
||||
emitTrailingComments(node: TextRange, comments?: CommentRange[]): void { },
|
||||
};
|
||||
|
||||
function emitDetachedComments(node: TextRange): void {
|
||||
@@ -53,41 +59,85 @@ namespace ts {
|
||||
return {
|
||||
reset,
|
||||
setSourceFile,
|
||||
getLeadingCommentsToEmit,
|
||||
getTrailingCommentsToEmit,
|
||||
emitDetachedComments,
|
||||
getLeadingComments,
|
||||
getLeadingCommentsOfPosition,
|
||||
getTrailingComments,
|
||||
getTrailingCommentsOfPosition,
|
||||
emitLeadingComments,
|
||||
emitTrailingComments,
|
||||
emitDetachedComments,
|
||||
};
|
||||
|
||||
function getLeadingCommentsToEmit(node: TextRange) {
|
||||
if (nodeIsSynthesized(node)) {
|
||||
return;
|
||||
function getLeadingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
|
||||
let comments = getLeadingCommentsOfPosition(range.pos);
|
||||
if (getAdditionalRange) {
|
||||
let additionalRange = getAdditionalRange(<Node>range);
|
||||
while (additionalRange) {
|
||||
comments = concatenate(
|
||||
getLeadingCommentsOfPosition(additionalRange.pos),
|
||||
comments
|
||||
);
|
||||
|
||||
additionalRange = getAdditionalRange(additionalRange);
|
||||
}
|
||||
}
|
||||
|
||||
if (!leadingCommentRangeNodeStarts[node.pos]) {
|
||||
leadingCommentRangeNodeStarts[node.pos] = true;
|
||||
const comments = hasDetachedComments(node.pos)
|
||||
? getLeadingCommentsWithoutDetachedComments()
|
||||
: getLeadingCommentRanges(currentText, node.pos);
|
||||
return consumeCommentRanges(comments);
|
||||
}
|
||||
|
||||
return noComments;
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getTrailingCommentsToEmit(node: TextRange) {
|
||||
if (nodeIsSynthesized(node)) {
|
||||
return;
|
||||
function getTrailingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
|
||||
let comments = getTrailingCommentsOfPosition(range.end);
|
||||
if (getAdditionalRange) {
|
||||
let additionalRange = getAdditionalRange(<Node>range);
|
||||
while (additionalRange) {
|
||||
comments = concatenate(
|
||||
comments,
|
||||
getTrailingCommentsOfPosition(additionalRange.end)
|
||||
);
|
||||
|
||||
additionalRange = getAdditionalRange(additionalRange);
|
||||
}
|
||||
}
|
||||
|
||||
if (!trailingCommentRangeNodeEnds[node.end]) {
|
||||
trailingCommentRangeNodeEnds[node.end] = true;
|
||||
const comments = getTrailingCommentRanges(currentText, node.end);
|
||||
return consumeCommentRanges(comments);
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getLeadingCommentsOfPosition(pos: number) {
|
||||
if (positionIsSynthesized(pos) || leadingCommentRangePositions[pos]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return noComments;
|
||||
leadingCommentRangePositions[pos] = true;
|
||||
const comments = hasDetachedComments(pos)
|
||||
? getLeadingCommentsWithoutDetachedComments()
|
||||
: getLeadingCommentRanges(currentText, pos);
|
||||
return consumeCommentRanges(comments);
|
||||
}
|
||||
|
||||
function getTrailingCommentsOfPosition(pos: number) {
|
||||
if (positionIsSynthesized(pos) || trailingCommentRangePositions[pos]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
trailingCommentRangePositions[pos] = true;
|
||||
const comments = getTrailingCommentRanges(currentText, pos);
|
||||
return consumeCommentRanges(comments);
|
||||
}
|
||||
|
||||
function emitLeadingComments(range: TextRange, comments = getLeadingComments(range)) {
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, range, comments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingComments(range: TextRange, comments = getTrailingComments(range)) {
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitDetachedComments(range: TextRange) {
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false);
|
||||
}
|
||||
|
||||
function hasConsumedCommentRange(comment: CommentRange) {
|
||||
@@ -136,22 +186,6 @@ namespace ts {
|
||||
|
||||
return noComments;
|
||||
}
|
||||
|
||||
function emitLeadingComments(range: TextRange, leadingComments: CommentRange[] = getLeadingCommentsToEmit(range)) {
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, range, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingComments(range: TextRange, trailingComments = getTrailingCommentsToEmit(range)) {
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitDetachedComments(range: TextRange) {
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
@@ -160,8 +194,8 @@ namespace ts {
|
||||
currentLineMap = undefined;
|
||||
detachedCommentsInfo = undefined;
|
||||
consumedCommentRanges = undefined;
|
||||
trailingCommentRangeNodeEnds = undefined;
|
||||
leadingCommentRangeNodeStarts = undefined;
|
||||
trailingCommentRangePositions = undefined;
|
||||
leadingCommentRangePositions = undefined;
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
@@ -170,8 +204,8 @@ namespace ts {
|
||||
currentLineMap = getLineStarts(sourceFile);
|
||||
detachedCommentsInfo = undefined;
|
||||
consumedCommentRanges = [];
|
||||
leadingCommentRangeNodeStarts = [];
|
||||
trailingCommentRangeNodeEnds = [];
|
||||
leadingCommentRangePositions = [];
|
||||
trailingCommentRangePositions = [];
|
||||
}
|
||||
|
||||
function hasDetachedComments(pos: number) {
|
||||
|
||||
@@ -292,9 +292,9 @@ namespace ts {
|
||||
return ~low;
|
||||
}
|
||||
|
||||
export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T) => U, initial: U): U;
|
||||
export function reduceLeft<T>(array: T[], f: (memo: T, value: T) => T): T;
|
||||
export function reduceLeft<T>(array: T[], f: (memo: T, value: T) => T, initial?: T): T {
|
||||
export function reduceLeft<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
|
||||
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
|
||||
export function reduceLeft<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
|
||||
if (array) {
|
||||
const count = array.length;
|
||||
if (count > 0) {
|
||||
@@ -308,7 +308,7 @@ namespace ts {
|
||||
result = initial;
|
||||
}
|
||||
while (pos < count) {
|
||||
result = f(result, array[pos]);
|
||||
result = f(result, array[pos], pos);
|
||||
pos++;
|
||||
}
|
||||
return result;
|
||||
@@ -317,9 +317,9 @@ namespace ts {
|
||||
return initial;
|
||||
}
|
||||
|
||||
export function reduceRight<T, U>(array: T[], f: (memo: U, value: T) => U, initial: U): U;
|
||||
export function reduceRight<T>(array: T[], f: (memo: T, value: T) => T): T;
|
||||
export function reduceRight<T>(array: T[], f: (memo: T, value: T) => T, initial?: T): T {
|
||||
export function reduceRight<T, U>(array: T[], f: (memo: U, value: T, i: number) => U, initial: U): U;
|
||||
export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T): T;
|
||||
export function reduceRight<T>(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T): T {
|
||||
if (array) {
|
||||
let pos = array.length - 1;
|
||||
if (pos >= 0) {
|
||||
@@ -332,7 +332,7 @@ namespace ts {
|
||||
result = initial;
|
||||
}
|
||||
while (pos >= 0) {
|
||||
result = f(result, array[pos]);
|
||||
result = f(result, array[pos], pos);
|
||||
pos--;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace ts {
|
||||
// Emit reference in dts, if the file reference was not already emitted
|
||||
if (referencedFile && !contains(emittedReferencedFiles, referencedFile)) {
|
||||
// Add a reference to generated dts file,
|
||||
// global file reference is added only
|
||||
// global file reference is added only
|
||||
// - if it is not bundled emit (because otherwise it would be self reference)
|
||||
// - and it is not already added
|
||||
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
|
||||
@@ -144,7 +144,7 @@ namespace ts {
|
||||
|
||||
if (!isBundledEmit && isExternalModule(sourceFile) && sourceFile.moduleAugmentations.length && !resultHasExternalModuleIndicator) {
|
||||
// if file was external module with augmentations - this fact should be preserved in .d.ts as well.
|
||||
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
|
||||
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
|
||||
// that will force compiler to think that this file is an external module - 'export {}' is a reasonable choice here.
|
||||
write("export {};");
|
||||
writeLine();
|
||||
@@ -349,7 +349,7 @@ namespace ts {
|
||||
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
|
||||
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
|
||||
emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeCommentRange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,7 +736,7 @@ namespace ts {
|
||||
|
||||
function emitExternalModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration) {
|
||||
// emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations).
|
||||
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
|
||||
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
|
||||
// external modules since they are indistingushable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}'
|
||||
// so compiler will treat them as external modules.
|
||||
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration;
|
||||
|
||||
+48
-18
@@ -287,12 +287,8 @@ namespace ts {
|
||||
_i = 0x10000000, // Use/preference flag for '_i'
|
||||
}
|
||||
|
||||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
return printFiles(resolver, host, targetSourceFile);
|
||||
}
|
||||
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
export function legacyEmitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
// emit output for the __extends helper function
|
||||
const extendsHelper = `
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
@@ -1919,7 +1915,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
if (multiLine) {
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
}
|
||||
|
||||
write(")");
|
||||
@@ -2246,6 +2241,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
return node;
|
||||
}
|
||||
|
||||
function skipAssertions(node: Expression): Expression {
|
||||
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
|
||||
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function emitCallTarget(node: Expression): Expression {
|
||||
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword) {
|
||||
emit(node);
|
||||
@@ -2695,7 +2697,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
}
|
||||
|
||||
function synthesizedNodeStartsOnNewLine(node: Node) {
|
||||
return nodeIsSynthesized(node) && (<SynthesizedNode>node).startsOnNewLine;
|
||||
return nodeIsSynthesized(node) && node.startsOnNewLine;
|
||||
}
|
||||
|
||||
function emitConditionalExpression(node: ConditionalExpression) {
|
||||
@@ -3312,8 +3314,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
// we can't reuse 'arr' because it might be modified within the body of the loop.
|
||||
const counter = createTempVariable(TempFlags._i);
|
||||
const rhsReference = createSynthesizedNode(SyntaxKind.Identifier) as Identifier;
|
||||
rhsReference.text = node.expression.kind === SyntaxKind.Identifier ?
|
||||
makeUniqueName((<Identifier>node.expression).text) :
|
||||
const expressionWithoutAssertions = skipAssertions(node.expression);
|
||||
rhsReference.text = expressionWithoutAssertions.kind === SyntaxKind.Identifier ?
|
||||
makeUniqueName((<Identifier>expressionWithoutAssertions).text) :
|
||||
makeTempVariableName(TempFlags.Auto);
|
||||
|
||||
// This is the let keyword for the counter and rhsReference. The let keyword for
|
||||
@@ -4328,7 +4331,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
writeLine();
|
||||
emitStart(restParam);
|
||||
emitNodeWithCommentsAndWithoutSourcemap(restParam.name);
|
||||
write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
|
||||
write(restIndex > 0
|
||||
? `[${tempName} - ${restIndex}] = arguments[${tempName}];`
|
||||
: `[${tempName}] = arguments[${tempName}];`);
|
||||
emitEnd(restParam);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
@@ -5344,6 +5349,18 @@ const _super = (function (geti, seti) {
|
||||
write(" = ");
|
||||
}
|
||||
|
||||
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
|
||||
const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
|
||||
let tempVariable: Identifier;
|
||||
|
||||
if (isClassExpressionWithStaticProperties) {
|
||||
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
|
||||
write("(");
|
||||
increaseIndent();
|
||||
emit(tempVariable);
|
||||
write(" = ");
|
||||
}
|
||||
|
||||
write("(function (");
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
@@ -5373,9 +5390,6 @@ const _super = (function (geti, seti) {
|
||||
writeLine();
|
||||
emitConstructor(node, baseTypeNode);
|
||||
emitMemberFunctionsForES5AndLower(node);
|
||||
emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true));
|
||||
writeLine();
|
||||
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
|
||||
writeLine();
|
||||
emitToken(SyntaxKind.CloseBraceToken, node.members.end, () => {
|
||||
write("return ");
|
||||
@@ -5402,7 +5416,23 @@ const _super = (function (geti, seti) {
|
||||
write("))");
|
||||
if (node.kind === SyntaxKind.ClassDeclaration) {
|
||||
write(";");
|
||||
emitPropertyDeclarations(node, staticProperties);
|
||||
writeLine();
|
||||
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
|
||||
}
|
||||
else if (isClassExpressionWithStaticProperties) {
|
||||
for (const property of staticProperties) {
|
||||
write(",");
|
||||
writeLine();
|
||||
emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true);
|
||||
}
|
||||
write(",");
|
||||
writeLine();
|
||||
emit(tempVariable);
|
||||
decreaseIndent();
|
||||
write(")");
|
||||
}
|
||||
|
||||
emitEnd(node);
|
||||
|
||||
if (node.kind === SyntaxKind.ClassDeclaration) {
|
||||
@@ -7941,7 +7971,7 @@ const _super = (function (geti, seti) {
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitTrailingComments(node: Node) {
|
||||
@@ -7953,7 +7983,7 @@ const _super = (function (geti, seti) {
|
||||
const trailingComments = getTrailingCommentsToEmit(node);
|
||||
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7968,8 +7998,8 @@ const _super = (function (geti, seti) {
|
||||
|
||||
const trailingComments = getTrailingCommentRanges(currentText, pos);
|
||||
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitLeadingCommentsOfPositionWorker(pos: number) {
|
||||
@@ -7990,7 +8020,7 @@ const _super = (function (geti, seti) {
|
||||
emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments);
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
}
|
||||
|
||||
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange) {
|
||||
|
||||
+295
-52
@@ -92,7 +92,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
|
||||
const node = <SynthesizedNode>createNode(kind, /*location*/ undefined);
|
||||
const node = createNode(kind, /*location*/ undefined);
|
||||
node.startsOnNewLine = startsOnNewLine;
|
||||
return node;
|
||||
}
|
||||
@@ -153,20 +153,20 @@ namespace ts {
|
||||
|
||||
// Literals
|
||||
|
||||
export function createLiteral(value: string): StringLiteral;
|
||||
export function createLiteral(value: number): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression;
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression {
|
||||
export function createLiteral(value: string, location?: TextRange): StringLiteral;
|
||||
export function createLiteral(value: number, location?: TextRange): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression;
|
||||
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression {
|
||||
if (typeof value === "number") {
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral);
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location);
|
||||
}
|
||||
else {
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location);
|
||||
node.text = String(value);
|
||||
return node;
|
||||
}
|
||||
@@ -203,8 +203,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createThis() {
|
||||
const node = <PrimaryExpression>createNode(SyntaxKind.ThisKeyword);
|
||||
export function createThis(location?: TextRange) {
|
||||
const node = <PrimaryExpression>createNode(SyntaxKind.ThisKeyword, location);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -267,8 +267,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression) {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
|
||||
export function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange) {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter, location);
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.dotDotDotToken = undefined;
|
||||
@@ -288,8 +288,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createObjectLiteral(properties?: ObjectLiteralElement[]) {
|
||||
const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
|
||||
export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange) {
|
||||
const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression, location);
|
||||
node.properties = createNodeArray(properties);
|
||||
return node;
|
||||
}
|
||||
@@ -316,6 +316,13 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createNew(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
|
||||
const node = <NewExpression>createNode(SyntaxKind.NewExpression, location);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.arguments = argumentsArray ? createNodeArray(argumentsArray) : undefined;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createParen(expression: Expression, location?: TextRange) {
|
||||
const node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression, location);
|
||||
node.expression = expression;
|
||||
@@ -347,13 +354,20 @@ namespace ts {
|
||||
|
||||
export function createTypeOf(expression: Expression) {
|
||||
const node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
|
||||
node.expression = parenthesizeForUnary(expression);
|
||||
node.expression = parenthesizePrefixOperand(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createVoid(expression: Expression) {
|
||||
const node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
node.expression = parenthesizeForUnary(expression);
|
||||
node.expression = parenthesizePrefixOperand(expression);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createPostfix(operand: Expression, operator: SyntaxKind, location?: TextRange) {
|
||||
const node = <PostfixUnaryExpression>createNode(SyntaxKind.PostfixUnaryExpression, location);
|
||||
node.operand = parenthesizePostfixOperand(operand);
|
||||
node.operator = operator;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -442,14 +456,64 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createEmptyStatement(location: TextRange) {
|
||||
return <EmptyStatement>createNode(SyntaxKind.EmptyStatement, location);
|
||||
}
|
||||
|
||||
export function createStatement(expression: Expression, location?: TextRange): ExpressionStatement {
|
||||
const node = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createReturn(expression?: Expression): ReturnStatement {
|
||||
const node = <ReturnStatement>createSynthesizedNode(SyntaxKind.ReturnStatement);
|
||||
export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange) {
|
||||
const node = <IfStatement>createNode(SyntaxKind.IfStatement, location);
|
||||
node.expression = expression;
|
||||
node.thenStatement = thenStatement;
|
||||
node.elseStatement = elseStatement;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement, location?: TextRange) {
|
||||
const node = <ForStatement>createNode(SyntaxKind.ForStatement, location);
|
||||
node.initializer = initializer;
|
||||
node.condition = condition;
|
||||
node.incrementor = incrementor;
|
||||
node.statement = statement;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createLabel(label: string | Identifier, statement: Statement, location?: TextRange) {
|
||||
const node = <LabeledStatement>createNode(SyntaxKind.LabeledStatement, location);
|
||||
node.label = typeof label === "string" ? createIdentifier(label) : label;
|
||||
node.statement = statement;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createDo(expression: Expression, statement: Statement, location?: TextRange) {
|
||||
const node = <DoStatement>createNode(SyntaxKind.DoStatement, location);
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createWhile(statement: Statement, expression: Expression, location?: TextRange) {
|
||||
const node = <WhileStatement>createNode(SyntaxKind.WhileStatement, location);
|
||||
node.statement = statement;
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange) {
|
||||
const node = <ForInStatement>createNode(SyntaxKind.ForInStatement, location);
|
||||
node.initializer = initializer;
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createReturn(expression?: Expression, location?: TextRange): ReturnStatement {
|
||||
const node = <ReturnStatement>createNode(SyntaxKind.ReturnStatement, location);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
@@ -516,9 +580,9 @@ namespace ts {
|
||||
|
||||
// Property assignments
|
||||
|
||||
export function createPropertyAssignment(name: PropertyName, initializer: Expression) {
|
||||
const node = <PropertyAssignment>createNode(SyntaxKind.PropertyAssignment);
|
||||
node.name = name;
|
||||
export function createPropertyAssignment(name: string | PropertyName, initializer: Expression, location?: TextRange) {
|
||||
const node = <PropertyAssignment>createNode(SyntaxKind.PropertyAssignment, location);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.questionToken = undefined;
|
||||
node.initializer = initializer;
|
||||
return node;
|
||||
@@ -526,18 +590,18 @@ namespace ts {
|
||||
|
||||
// Compound nodes
|
||||
|
||||
export function createComma(left: Expression, right: Expression) {
|
||||
return <Expression>createBinary(left, SyntaxKind.CommaToken, right);
|
||||
}
|
||||
|
||||
export function createLessThan(left: Expression, right: Expression, location?: TextRange) {
|
||||
return <Expression>createBinary(left, SyntaxKind.LessThanToken, right, location);
|
||||
}
|
||||
|
||||
export function createAssignment(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createBinary(left, SyntaxKind.EqualsToken, right, location);
|
||||
}
|
||||
|
||||
export function createLogicalAnd(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.AmpersandAmpersandToken, right);
|
||||
}
|
||||
|
||||
export function createLogicalOr(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.BarBarToken, right);
|
||||
}
|
||||
|
||||
export function createStrictEquality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.EqualsEqualsEqualsToken, right);
|
||||
}
|
||||
@@ -546,8 +610,24 @@ namespace ts {
|
||||
return createBinary(left, SyntaxKind.ExclamationEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createComma(left: Expression, right: Expression) {
|
||||
return <Expression>createBinary(left, SyntaxKind.CommaToken, right);
|
||||
export function createAdd(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.PlusToken, right);
|
||||
}
|
||||
|
||||
export function createSubtract(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.MinusToken, right);
|
||||
}
|
||||
|
||||
export function createPostfixIncrement(operand: Expression, location?: TextRange) {
|
||||
return createPostfix(operand, SyntaxKind.PlusPlusToken, location);
|
||||
}
|
||||
|
||||
export function createLogicalAnd(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.AmpersandAmpersandToken, right);
|
||||
}
|
||||
|
||||
export function createLogicalOr(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.BarBarToken, right);
|
||||
}
|
||||
|
||||
export function createVoidZero() {
|
||||
@@ -566,6 +646,28 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange) {
|
||||
return createCall(
|
||||
createPropertyAccess(func, "call"),
|
||||
[
|
||||
thisArg,
|
||||
...argumentsList
|
||||
],
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
export function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange) {
|
||||
return createCall(
|
||||
createPropertyAccess(func, "apply"),
|
||||
[
|
||||
thisArg,
|
||||
argumentsExpression
|
||||
],
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
export function createArraySlice(array: Expression, start?: number | Expression) {
|
||||
const argumentsList: Expression[] = [];
|
||||
if (start !== undefined) {
|
||||
@@ -575,6 +677,13 @@ namespace ts {
|
||||
return createCall(createPropertyAccess(array, "slice"), argumentsList);
|
||||
}
|
||||
|
||||
export function createArrayConcat(array: Expression, values: Expression[]) {
|
||||
return createCall(
|
||||
createPropertyAccess(array, "concat"),
|
||||
values
|
||||
);
|
||||
}
|
||||
|
||||
export function createMathPow(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createCall(
|
||||
createPropertyAccess(createIdentifier("Math"), "pow"),
|
||||
@@ -618,6 +727,16 @@ namespace ts {
|
||||
|
||||
// Helpers
|
||||
|
||||
export function createExtendsHelper(name: Identifier) {
|
||||
return createCall(
|
||||
createIdentifier("__extends"),
|
||||
[
|
||||
name,
|
||||
createIdentifier("_super")
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function createParamHelper(expression: Expression, parameterOffset: number) {
|
||||
return createCall(
|
||||
createIdentifier("__param"),
|
||||
@@ -671,6 +790,56 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
function createPropertyDescriptor({ get, set, value, enumerable, configurable, writable }: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange) {
|
||||
const properties: ObjectLiteralElement[] = [];
|
||||
addPropertyAssignment(properties, "get", get, preferNewLine);
|
||||
addPropertyAssignment(properties, "set", set, preferNewLine);
|
||||
addPropertyAssignment(properties, "value", value, preferNewLine);
|
||||
addPropertyAssignment(properties, "enumerable", enumerable, preferNewLine);
|
||||
addPropertyAssignment(properties, "configurable", configurable, preferNewLine);
|
||||
addPropertyAssignment(properties, "writable", writable, preferNewLine);
|
||||
return createObjectLiteral(properties, location)
|
||||
}
|
||||
|
||||
function addPropertyAssignment(properties: ObjectLiteralElement[], name: string, value: boolean | Expression, preferNewLine: boolean) {
|
||||
if (value !== undefined) {
|
||||
const property = createPropertyAssignment(
|
||||
name,
|
||||
typeof value === "boolean" ? createLiteral(value) : value
|
||||
);
|
||||
|
||||
if (preferNewLine) {
|
||||
startOnNewLine(property);
|
||||
}
|
||||
|
||||
addNode(properties, property);
|
||||
}
|
||||
}
|
||||
|
||||
export interface PropertyDescriptorOptions {
|
||||
get?: Expression;
|
||||
set?: Expression;
|
||||
value?: Expression;
|
||||
enumerable?: boolean | Expression;
|
||||
configurable?: boolean | Expression;
|
||||
writable?: boolean | Expression;
|
||||
}
|
||||
|
||||
export function createObjectDefineProperty(target: Expression, memberName: Expression, descriptor: PropertyDescriptorOptions, preferNewLine?: boolean, location?: TextRange) {
|
||||
return createCall(
|
||||
createPropertyAccess(
|
||||
createIdentifier("Object"),
|
||||
"defineProperty"
|
||||
),
|
||||
[
|
||||
target,
|
||||
memberName,
|
||||
createPropertyDescriptor(descriptor, preferNewLine)
|
||||
],
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function createObjectCreate(prototype: Expression) {
|
||||
return createCall(
|
||||
createPropertyAccess(createIdentifier("Object"), "create"),
|
||||
@@ -839,6 +1008,12 @@ namespace ts {
|
||||
: cloneNode(node);
|
||||
}
|
||||
|
||||
export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression {
|
||||
return isIdentifier(memberName) ? createLiteral(memberName.text, location)
|
||||
: isComputedPropertyName(memberName) ? cloneNode(memberName.expression, location)
|
||||
: cloneNode(memberName, location);
|
||||
}
|
||||
|
||||
|
||||
// Utilities
|
||||
/**
|
||||
@@ -850,11 +1025,7 @@ namespace ts {
|
||||
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
|
||||
* BinaryExpression.
|
||||
*/
|
||||
function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean) {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
operand = skipAssertions(operand);
|
||||
|
||||
export function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean) {
|
||||
// If the resulting expression is already parenthesized, we do not need to do any further processing.
|
||||
if (operand.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
return operand;
|
||||
@@ -968,11 +1139,7 @@ namespace ts {
|
||||
*
|
||||
* @param expr The expression node.
|
||||
*/
|
||||
function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
expr = skipAssertions(expr);
|
||||
|
||||
export function parenthesizeForAccess(expression: Expression): LeftHandSideExpression {
|
||||
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
|
||||
// to parenthesize the expression before a dot. The known exceptions are:
|
||||
//
|
||||
@@ -981,21 +1148,86 @@ namespace ts {
|
||||
// NumericLiteral
|
||||
// 1.x -> not the same as (1).x
|
||||
//
|
||||
if (isLeftHandSideExpression(expr) &&
|
||||
expr.kind !== SyntaxKind.NewExpression &&
|
||||
expr.kind !== SyntaxKind.NumericLiteral) {
|
||||
return expr;
|
||||
if (isLeftHandSideExpression(expression) &&
|
||||
expression.kind !== SyntaxKind.NewExpression &&
|
||||
expression.kind !== SyntaxKind.NumericLiteral) {
|
||||
return <LeftHandSideExpression>expression;
|
||||
}
|
||||
|
||||
return createParen(expr);
|
||||
return createParen(expression, /*location*/ expression);
|
||||
}
|
||||
|
||||
function parenthesizeForUnary(operand: Expression) {
|
||||
if (isUnaryExpression(operand)) {
|
||||
return operand;
|
||||
export function parenthesizePostfixOperand(operand: Expression) {
|
||||
return isLeftHandSideExpression(operand)
|
||||
? <LeftHandSideExpression>operand
|
||||
: createParen(operand, /*location*/ operand);
|
||||
}
|
||||
|
||||
export function parenthesizePrefixOperand(operand: Expression) {
|
||||
return isUnaryExpression(operand)
|
||||
? <UnaryExpression>operand
|
||||
: createParen(operand, /*location*/ operand);
|
||||
}
|
||||
|
||||
export function parenthesizeExpressionForList(expression: Expression) {
|
||||
const expressionPrecedence = getExpressionPrecedence(expression);
|
||||
const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken);
|
||||
return expressionPrecedence > commaPrecedence
|
||||
? expression
|
||||
: createParen(expression, /*location*/ expression);
|
||||
}
|
||||
|
||||
export function parenthesizeExpressionForExpressionStatement(expression: Expression) {
|
||||
if (isCallExpression(expression)) {
|
||||
const callee = expression.expression;
|
||||
if (callee.kind === SyntaxKind.FunctionExpression
|
||||
|| callee.kind === SyntaxKind.ArrowFunction) {
|
||||
const clone = cloneNode(expression, expression, expression.flags, expression.parent, expression);
|
||||
clone.expression = createParen(callee, /*location*/ callee);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
else if (getLeftmostExpression(expression).kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return createParen(expression, /*location*/ expression);
|
||||
}
|
||||
|
||||
return createParen(operand);
|
||||
return expression;
|
||||
}
|
||||
|
||||
function getLeftmostExpression(node: Expression): Expression {
|
||||
while (true) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
node = (<PostfixUnaryExpression>node).operand;
|
||||
continue;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
node = (<BinaryExpression>node).left;
|
||||
continue;
|
||||
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
node = (<ConditionalExpression>node).condition;
|
||||
continue;
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
node = (<CallExpression | PropertyAccessExpression | ElementAccessExpression>node).expression;
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export function skipParentheses(node: Expression): Expression {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression
|
||||
|| node.kind === SyntaxKind.TypeAssertionExpression
|
||||
|| node.kind === SyntaxKind.AsExpression) {
|
||||
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1004,7 +1236,8 @@ namespace ts {
|
||||
* @param node The expression node.
|
||||
*/
|
||||
function skipAssertions(node: Expression) {
|
||||
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
|
||||
while (node.kind === SyntaxKind.TypeAssertionExpression
|
||||
|| node.kind === SyntaxKind.AsExpression) {
|
||||
node = (<AssertionExpression>node).expression;
|
||||
}
|
||||
|
||||
@@ -1012,7 +1245,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function startOnNewLine<T extends Node>(node: T): T {
|
||||
(<SynthesizedNode>node).startsOnNewLine = true;
|
||||
node.startsOnNewLine = true;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1034,6 +1267,16 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setMultiLine<T extends ObjectLiteralExpression | ArrayLiteralExpression | Block>(node: T, multiLine: boolean): T {
|
||||
node.multiLine = multiLine;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setHasTrailingComma<T extends Node>(nodes: NodeArray<T>, hasTrailingComma: boolean): NodeArray<T> {
|
||||
nodes.hasTrailingComma = hasTrailingComma;
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export function getSynthesizedNode<T extends Node>(node: T): T {
|
||||
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
}
|
||||
|
||||
@@ -4069,6 +4069,10 @@ namespace ts {
|
||||
function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
|
||||
const node = <Block>createNode(SyntaxKind.Block);
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
|
||||
if (scanner.hasPrecedingLineBreak()) {
|
||||
node.multiLine = true;
|
||||
}
|
||||
|
||||
node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
|
||||
+147
-90
@@ -119,13 +119,31 @@ const _super = (function (geti, seti) {
|
||||
const transformers = getTransformers(compilerOptions).concat(initializePrinter);
|
||||
|
||||
const writer = createTextWriter(newLine);
|
||||
const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
|
||||
const {
|
||||
write,
|
||||
writeTextOfNode,
|
||||
writeLine,
|
||||
increaseIndent,
|
||||
decreaseIndent
|
||||
} = writer;
|
||||
|
||||
const sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter();
|
||||
const { emitStart, emitEnd, emitPos } = sourceMap;
|
||||
const {
|
||||
emitStart,
|
||||
emitEnd,
|
||||
emitPos
|
||||
} = sourceMap;
|
||||
|
||||
const comments = createCommentWriter(host, writer, sourceMap);
|
||||
const { emitDetachedComments, emitLeadingComments, emitTrailingComments, getLeadingCommentsToEmit, getTrailingCommentsToEmit } = comments;
|
||||
const {
|
||||
getLeadingComments,
|
||||
getLeadingCommentsOfPosition,
|
||||
getTrailingComments,
|
||||
getTrailingCommentsOfPosition,
|
||||
emitLeadingComments,
|
||||
emitTrailingComments,
|
||||
emitDetachedComments
|
||||
} = comments;
|
||||
|
||||
let context: TransformationContext;
|
||||
let startLexicalEnvironment: () => void;
|
||||
@@ -233,14 +251,22 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function emit(node: Node) {
|
||||
emitWithWorker(node, emitWorker);
|
||||
}
|
||||
|
||||
function emitExpression(node: Expression) {
|
||||
emitWithWorker(node, emitExpressionWorker);
|
||||
}
|
||||
|
||||
function emitWithWorker(node: Node, emitWorker: (node: Node) => void) {
|
||||
if (node) {
|
||||
const adviseOnEmit = isEmitNotificationEnabled(node);
|
||||
if (adviseOnEmit && onBeforeEmitNode) {
|
||||
onBeforeEmitNode(node);
|
||||
}
|
||||
|
||||
const leadingComments = getLeadingCommentsToEmit(node);
|
||||
const trailingComments = getTrailingCommentsToEmit(node);
|
||||
const leadingComments = getLeadingComments(node, getNotEmittedParent);
|
||||
const trailingComments = getTrailingComments(node, getNotEmittedParent);
|
||||
emitLeadingComments(node, leadingComments);
|
||||
emitStart(node);
|
||||
emitWorker(node);
|
||||
@@ -253,7 +279,18 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
}
|
||||
|
||||
function emitWorker(node: Node) {
|
||||
function getNotEmittedParent(node: Node): Node {
|
||||
if (getNodeEmitFlags(node) & NodeEmitFlags.EmitCommentsOfNotEmittedParent) {
|
||||
const parent = getOriginalNode(node).parent;
|
||||
if (getNodeEmitFlags(parent) & NodeEmitFlags.IsNotEmittedNode) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function emitWorker(node: Node): void {
|
||||
const kind = node.kind;
|
||||
switch (kind) {
|
||||
// Pseudo-literals
|
||||
@@ -358,7 +395,7 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>node);
|
||||
case SyntaxKind.ThisType:
|
||||
return write("this");
|
||||
return emitThisType(<ThisTypeNode>node);
|
||||
case SyntaxKind.StringLiteralType:
|
||||
return emitLiteral(<StringLiteralTypeNode>node);
|
||||
|
||||
@@ -374,7 +411,7 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.TemplateSpan:
|
||||
return emitTemplateSpan(<TemplateSpan>node);
|
||||
case SyntaxKind.SemicolonClassElement:
|
||||
return write(";");
|
||||
return emitSemicolonClassElement(<SemicolonClassElement>node);
|
||||
|
||||
// Statements
|
||||
case SyntaxKind.Block:
|
||||
@@ -382,7 +419,7 @@ const _super = (function (geti, seti) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
return emitVariableStatement(<VariableStatement>node);
|
||||
case SyntaxKind.EmptyStatement:
|
||||
return write(";");
|
||||
return emitEmptyStatement(<EmptyStatement>node);
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return emitExpressionStatement(<ExpressionStatement>node);
|
||||
case SyntaxKind.IfStatement:
|
||||
@@ -501,23 +538,11 @@ const _super = (function (geti, seti) {
|
||||
// JSDoc nodes (ignored)
|
||||
}
|
||||
|
||||
if (isExpressionKind(kind)) {
|
||||
if (isExpression(node)) {
|
||||
return emitExpressionWorker(node);
|
||||
}
|
||||
}
|
||||
|
||||
function emitExpression(node: Expression) {
|
||||
if (node) {
|
||||
const leadingComments = getLeadingCommentsToEmit(node);
|
||||
const trailingComments = getTrailingCommentsToEmit(node);
|
||||
emitLeadingComments(node, leadingComments);
|
||||
emitStart(node);
|
||||
emitExpressionWorker(node);
|
||||
emitEnd(node);
|
||||
emitTrailingComments(node, trailingComments);
|
||||
}
|
||||
}
|
||||
|
||||
function emitExpressionWorker(node: Node) {
|
||||
const kind = node.kind;
|
||||
if (isExpressionSubstitutionEnabled(node) && tryEmitSubstitute(node, expressionSubstitution)) {
|
||||
@@ -641,7 +666,7 @@ const _super = (function (geti, seti) {
|
||||
const text = temporaryVariables[nodeId] || (temporaryVariables[nodeId] = makeTempVariableName(tempKindToFlags(node.tempKind)));
|
||||
write(text);
|
||||
}
|
||||
else if (nodeIsSynthesized(node)) {
|
||||
else if (nodeIsSynthesized(node) || !node.parent) {
|
||||
if (getNodeEmitFlags(node) & NodeEmitFlags.UMDDefine) {
|
||||
writeLines(umdHelper);
|
||||
}
|
||||
@@ -741,13 +766,13 @@ const _super = (function (geti, seti) {
|
||||
emitModifiers(node, node.modifiers);
|
||||
writeIfPresent(node.asteriskToken, "*");
|
||||
emit(node.name);
|
||||
emitSignatureAndBody(node);
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitConstructor(node: ConstructorDeclaration) {
|
||||
emitModifiers(node, node.modifiers);
|
||||
write("constructor");
|
||||
emitSignatureAndBody(node);
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitAccessorDeclaration(node: AccessorDeclaration) {
|
||||
@@ -755,7 +780,7 @@ const _super = (function (geti, seti) {
|
||||
emitModifiers(node, node.modifiers);
|
||||
write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
|
||||
emit(node.name);
|
||||
emitSignatureAndBody(node);
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitCallSignature(node: CallSignatureDeclaration) {
|
||||
@@ -785,6 +810,10 @@ const _super = (function (geti, seti) {
|
||||
write(";");
|
||||
}
|
||||
|
||||
function emitSemicolonClassElement(node: SemicolonClassElement) {
|
||||
write(";");
|
||||
}
|
||||
|
||||
//
|
||||
// Types
|
||||
//
|
||||
@@ -851,6 +880,10 @@ const _super = (function (geti, seti) {
|
||||
write(")");
|
||||
}
|
||||
|
||||
function emitThisType(node: ThisTypeNode) {
|
||||
write("this");
|
||||
}
|
||||
|
||||
//
|
||||
// Binding patterns
|
||||
//
|
||||
@@ -896,7 +929,7 @@ const _super = (function (geti, seti) {
|
||||
write("[]");
|
||||
}
|
||||
else {
|
||||
const preferNewLine = getNodeEmitFlags(node) & NodeEmitFlags.MultiLine ? ListFormat.PreferNewLine : ListFormat.None;
|
||||
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
|
||||
emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine);
|
||||
}
|
||||
}
|
||||
@@ -907,7 +940,7 @@ const _super = (function (geti, seti) {
|
||||
write("{}");
|
||||
}
|
||||
else {
|
||||
const preferNewLine = getNodeEmitFlags(node) & NodeEmitFlags.MultiLine ? ListFormat.PreferNewLine : ListFormat.None;
|
||||
const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None;
|
||||
const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None;
|
||||
emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine);
|
||||
}
|
||||
@@ -998,27 +1031,8 @@ const _super = (function (geti, seti) {
|
||||
function emitArrowFunction(node: ArrowFunction) {
|
||||
emitDecorators(node, node.decorators);
|
||||
emitModifiers(node, node.modifiers);
|
||||
const body = node.body;
|
||||
if (isBlock(body)) {
|
||||
const savedTempFlags = tempFlags;
|
||||
tempFlags = 0;
|
||||
startLexicalEnvironment();
|
||||
emitArrowFunctionHead(node);
|
||||
write(" {");
|
||||
emitSignatureAndBody(node, emitArrowFunctionHead);
|
||||
|
||||
const startingLine = writer.getLine();
|
||||
emitBlockFunctionBody(node, body);
|
||||
|
||||
const endingLine = writer.getLine();
|
||||
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
|
||||
tempFlags = savedTempFlags;
|
||||
write("}");
|
||||
}
|
||||
else {
|
||||
emitArrowFunctionHead(node);
|
||||
write(" ");
|
||||
emitExpression(body);
|
||||
}
|
||||
}
|
||||
|
||||
function emitArrowFunctionHead(node: ArrowFunction) {
|
||||
@@ -1186,6 +1200,10 @@ const _super = (function (geti, seti) {
|
||||
write(";");
|
||||
}
|
||||
|
||||
function emitEmptyStatement(node: EmptyStatement) {
|
||||
write(";");
|
||||
}
|
||||
|
||||
function emitExpressionStatement(node: ExpressionStatement) {
|
||||
emitExpression(node.expression);
|
||||
write(";");
|
||||
@@ -1353,25 +1371,27 @@ const _super = (function (geti, seti) {
|
||||
emitModifiers(node, node.modifiers);
|
||||
write(node.asteriskToken ? "function* " : "function ");
|
||||
emit(node.name);
|
||||
emitSignatureAndBody(node);
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitSignatureAndBody(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) {
|
||||
function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) {
|
||||
const body = node.body;
|
||||
if (body) {
|
||||
const savedTempFlags = tempFlags;
|
||||
tempFlags = 0;
|
||||
startLexicalEnvironment();
|
||||
emitSignatureHead(node);
|
||||
write(" {");
|
||||
|
||||
const startingLine = writer.getLine();
|
||||
emitBlockFunctionBody(node, body);
|
||||
|
||||
const endingLine = writer.getLine();
|
||||
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
|
||||
write("}");
|
||||
tempFlags = savedTempFlags;
|
||||
if (isBlock(body)) {
|
||||
const savedTempFlags = tempFlags;
|
||||
tempFlags = 0;
|
||||
startLexicalEnvironment();
|
||||
emitSignatureHead(node);
|
||||
write(" {");
|
||||
emitBlockFunctionBody(node, body);
|
||||
write("}");
|
||||
tempFlags = savedTempFlags;
|
||||
}
|
||||
else {
|
||||
emitSignatureHead(node);
|
||||
write(" ");
|
||||
emitExpression(body);
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitSignatureHead(node);
|
||||
@@ -1388,37 +1408,49 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) {
|
||||
const originalNode = getOriginalNode(parentNode);
|
||||
if (isFunctionLike(originalNode) && !nodeIsSynthesized(originalNode) && rangeEndIsOnSameLineAsRangeStart(originalNode.body, originalNode.body)) {
|
||||
for (const statement of body.statements) {
|
||||
if (synthesizedNodeStartsOnNewLine(statement)) {
|
||||
return false;
|
||||
if (isFunctionLike(originalNode) && !nodeIsSynthesized(originalNode)) {
|
||||
const body = originalNode.body;
|
||||
if (isBlock(body)) {
|
||||
if (rangeEndIsOnSameLineAsRangeStart(body, body)) {
|
||||
for (const statement of body.statements) {
|
||||
if (synthesizedNodeStartsOnNewLine(statement)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (originalNode.kind === SyntaxKind.ArrowFunction && !rangeEndIsOnSameLineAsRangeStart((<ArrowFunction>originalNode).equalsGreaterThanToken, originalNode.body)) {
|
||||
return false;
|
||||
else {
|
||||
return rangeEndIsOnSameLineAsRangeStart((<ArrowFunction>originalNode).equalsGreaterThanToken, originalNode.body);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function emitBlockFunctionBody(parentNode: Node, body: Block) {
|
||||
// Emit all the prologue directives (like "use strict").
|
||||
const startingLine = writer.getLine();
|
||||
increaseIndent();
|
||||
const statements = body.statements;
|
||||
const statementOffset = emitPrologueDirectives(statements, /*startWithNewLine*/ true);
|
||||
emitDetachedComments(body.statements);
|
||||
|
||||
// Emit all the prologue directives (like "use strict").
|
||||
const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true);
|
||||
const helpersEmitted = emitHelpers(body);
|
||||
decreaseIndent();
|
||||
|
||||
if (statementOffset === 0 && !helpersEmitted && shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)) {
|
||||
emitList(body, statements, ListFormat.SingleLineFunctionBodyStatements);
|
||||
decreaseIndent();
|
||||
emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements);
|
||||
increaseIndent();
|
||||
}
|
||||
else {
|
||||
emitList(body, statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset);
|
||||
emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset);
|
||||
}
|
||||
|
||||
const endingLine = writer.getLine();
|
||||
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
|
||||
emitLeadingComments(collapseTextRange(body.statements, TextRangeCollapse.CollapseToEnd));
|
||||
decreaseIndent();
|
||||
}
|
||||
|
||||
function emitClassDeclaration(node: ClassDeclaration) {
|
||||
@@ -1688,6 +1720,8 @@ const _super = (function (geti, seti) {
|
||||
write("case ");
|
||||
emitExpression(node.expression);
|
||||
write(":");
|
||||
|
||||
debugger;
|
||||
emitCaseOrDefaultClauseStatements(node, node.statements);
|
||||
}
|
||||
|
||||
@@ -2051,8 +2085,10 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
else {
|
||||
// Write the opening line terminator or leading whitespace.
|
||||
let shouldEmitInterveningComments = true;
|
||||
if (shouldWriteLeadingLineTerminator(parentNode, children, format)) {
|
||||
writeLine();
|
||||
shouldEmitInterveningComments = false;
|
||||
}
|
||||
else if (format & ListFormat.SpaceBetweenBraces) {
|
||||
write(" ");
|
||||
@@ -2076,12 +2112,20 @@ const _super = (function (geti, seti) {
|
||||
// Write either a line terminator or whitespace to separate the elements.
|
||||
if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) {
|
||||
writeLine();
|
||||
shouldEmitInterveningComments = false;
|
||||
}
|
||||
else if (previousSibling) {
|
||||
write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldEmitInterveningComments) {
|
||||
emitLeadingComments(child, getTrailingCommentsOfPosition(child.pos));
|
||||
}
|
||||
else {
|
||||
shouldEmitInterveningComments = true;
|
||||
}
|
||||
|
||||
// Emit this child.
|
||||
emit(child);
|
||||
|
||||
@@ -2175,7 +2219,7 @@ const _super = (function (geti, seti) {
|
||||
return true;
|
||||
}
|
||||
else if (format & ListFormat.PreserveLines) {
|
||||
if (getNodeEmitFlags(parentNode) & NodeEmitFlags.MultiLine) {
|
||||
if (format & ListFormat.PreferNewLine) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2217,10 +2261,10 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray<Node>, format: ListFormat) {
|
||||
if (format & ListFormat.MultiLine) {
|
||||
return true;
|
||||
return (format & ListFormat.NoTrailingNewLine) === 0;
|
||||
}
|
||||
else if (format & ListFormat.PreserveLines) {
|
||||
if (getNodeEmitFlags(parentNode) & NodeEmitFlags.MultiLine) {
|
||||
if (format & ListFormat.PreferNewLine) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2242,7 +2286,7 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) {
|
||||
if (nodeIsSynthesized(node)) {
|
||||
const startsOnNewLine = (<SynthesizedNode>node).startsOnNewLine;
|
||||
const startsOnNewLine = node.startsOnNewLine;
|
||||
if (startsOnNewLine === undefined) {
|
||||
return (format & ListFormat.PreferNewLine) !== 0;
|
||||
}
|
||||
@@ -2274,8 +2318,12 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function needsIndentation(parent: Node, node1: Node, node2: Node): boolean {
|
||||
parent = skipSynthesizedParentheses(parent);
|
||||
node1 = skipSynthesizedParentheses(node1);
|
||||
node2 = skipSynthesizedParentheses(node2);
|
||||
|
||||
// Always use a newline for synthesized code if the synthesizer desires it.
|
||||
if (synthesizedNodeStartsOnNewLine(node2)) {
|
||||
if (node2.startsOnNewLine) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2285,6 +2333,14 @@ const _super = (function (geti, seti) {
|
||||
&& !rangeEndIsOnSameLineAsRangeStart(node1, node2);
|
||||
}
|
||||
|
||||
function skipSynthesizedParentheses(node: Node) {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) {
|
||||
node = (<ParenthesizedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function getTextOfNode(node: Node, includeTrivia?: boolean) {
|
||||
if (nodeIsSynthesized(node) && (isLiteralExpression(node) || isIdentifier(node))) {
|
||||
return node.text;
|
||||
@@ -2304,9 +2360,9 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
function isSingleLineEmptyBlock(block: Block) {
|
||||
return (getNodeEmitFlags(block) & NodeEmitFlags.MultiLine) === 0 &&
|
||||
block.statements.length === 0 &&
|
||||
rangeEndIsOnSameLineAsRangeStart(block, block);
|
||||
return !block.multiLine
|
||||
&& block.statements.length === 0
|
||||
&& rangeEndIsOnSameLineAsRangeStart(block, block);
|
||||
}
|
||||
|
||||
function tempKindToFlags(kind: TempVariableKind) {
|
||||
@@ -2361,7 +2417,7 @@ const _super = (function (geti, seti) {
|
||||
function createBracketsMap() {
|
||||
const brackets: string[][] = [];
|
||||
brackets[ListFormat.Braces] = ["{", "}"];
|
||||
brackets[ListFormat.Parenthesis] = ["(", ")"];
|
||||
brackets[ListFormat.Parenthesis] = ["(",")"];
|
||||
brackets[ListFormat.AngleBrackets] = ["<", ">"];
|
||||
brackets[ListFormat.SquareBrackets] = ["[", "]"];
|
||||
return brackets;
|
||||
@@ -2407,6 +2463,7 @@ const _super = (function (geti, seti) {
|
||||
|
||||
// Other
|
||||
PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes.
|
||||
NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list.
|
||||
|
||||
// Precomputed Formats
|
||||
TypeLiteralMembers = MultiLine | Indented,
|
||||
@@ -2424,7 +2481,7 @@ const _super = (function (geti, seti) {
|
||||
MultiLineBlockStatements = Indented | MultiLine,
|
||||
VariableDeclarationList = CommaDelimited | SingleLine,
|
||||
SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenBraces,
|
||||
MultiLineFunctionBodyStatements = MultiLine | Indented,
|
||||
MultiLineFunctionBodyStatements = MultiLine,
|
||||
ClassHeritageClauses = SingleLine,
|
||||
ClassMembers = Indented | MultiLine,
|
||||
InterfaceMembers = Indented | MultiLine,
|
||||
@@ -2433,9 +2490,9 @@ const _super = (function (geti, seti) {
|
||||
NamedImportsOrExportsElements = CommaDelimited | AllowTrailingComma | SingleLine | SpaceBetweenBraces,
|
||||
JsxElementChildren = SingleLine,
|
||||
JsxElementAttributes = SingleLine,
|
||||
CaseOrDefaultClauseStatements = Indented | MultiLine,
|
||||
CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty,
|
||||
HeritageClauseTypes = CommaDelimited | SingleLine,
|
||||
SourceFileStatements = MultiLine,
|
||||
SourceFileStatements = MultiLine | NoTrailingNewLine,
|
||||
Decorators = MultiLine | Optional,
|
||||
TypeArguments = CommaDelimited | SingleLine | Indented | AngleBrackets | Optional,
|
||||
TypeParameters = CommaDelimited | SingleLine | Indented | AngleBrackets | Optional,
|
||||
|
||||
@@ -968,7 +968,7 @@ namespace ts {
|
||||
|
||||
const start = new Date().getTime();
|
||||
|
||||
const emitResult = emitFiles(
|
||||
const emitResult = (options.experimentalTransforms ? printFiles : emitFiles)(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
|
||||
@@ -433,9 +433,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
|
||||
// Using ! with a greater than test is a fast way of testing the following conditions:
|
||||
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
|
||||
if (!(pos >= 0)) {
|
||||
if (positionIsSynthesized(pos)) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -642,6 +640,7 @@ namespace ts {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (collecting) {
|
||||
if (!result) {
|
||||
result = [];
|
||||
|
||||
@@ -310,13 +310,13 @@ namespace ts {
|
||||
function emitStart(range: TextRange) {
|
||||
emitPos(getStartPos(range));
|
||||
|
||||
if ((<SynthesizedNode>range).disableSourceMap) {
|
||||
if (range.disableSourceMap) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
function emitEnd(range: TextRange, stopOverridingEnd?: boolean) {
|
||||
if ((<SynthesizedNode>range).disableSourceMap) {
|
||||
if (range.disableSourceMap) {
|
||||
enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +84,12 @@ namespace ts {
|
||||
hoistFunctionDeclaration,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
identifierSubstitution: node => node,
|
||||
expressionSubstitution: node => node,
|
||||
enableExpressionSubstitution,
|
||||
isExpressionSubstitutionEnabled,
|
||||
onBeforeEmitNode: node => { },
|
||||
onAfterEmitNode: node => { },
|
||||
enableEmitNotification,
|
||||
isEmitNotificationEnabled,
|
||||
};
|
||||
@@ -148,8 +152,9 @@ namespace ts {
|
||||
/**
|
||||
* Sets flags that control emit behavior of a node.
|
||||
*/
|
||||
function setNodeEmitFlags(node: Node, flags: NodeEmitFlags) {
|
||||
function setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags) {
|
||||
nodeEmitFlags[getNodeId(node)] = flags;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace ts {
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
if (isSimpleExpression(value)) {
|
||||
(<SynthesizedNode>expression).disableSourceMap = true;
|
||||
expression.disableSourceMap = true;
|
||||
}
|
||||
|
||||
aggregateTransformFlags(expression);
|
||||
@@ -82,7 +82,7 @@ namespace ts {
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
|
||||
const declaration = createVariableDeclaration(name, value, location);
|
||||
if (isSimpleExpression(value)) {
|
||||
(<SynthesizedNode>declaration).disableSourceMap = true;
|
||||
declaration.disableSourceMap = true;
|
||||
}
|
||||
|
||||
aggregateTransformFlags(declaration);
|
||||
@@ -117,7 +117,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isSimpleExpression(value)) {
|
||||
(<SynthesizedNode>declaration).disableSourceMap = true;
|
||||
declaration.disableSourceMap = true;
|
||||
}
|
||||
|
||||
declaration.original = original;
|
||||
@@ -169,7 +169,7 @@ namespace ts {
|
||||
function emitPendingAssignment(name: Expression, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
if (isSimpleExpression(value)) {
|
||||
(<SynthesizedNode>expression).disableSourceMap = true;
|
||||
expression.disableSourceMap = true;
|
||||
}
|
||||
|
||||
expression.original = original;
|
||||
@@ -199,7 +199,7 @@ namespace ts {
|
||||
function emitDestructuringAssignment(bindingTarget: Expression | ShorthandPropertyAssignment, value: Expression, location: TextRange) {
|
||||
// When emitting target = value use source map node to highlight, including any temporary assignments needed for this
|
||||
let target: Expression;
|
||||
if (isShortHandPropertyAssignment(bindingTarget)) {
|
||||
if (isShorthandPropertyAssignment(bindingTarget)) {
|
||||
const initializer = visitor
|
||||
? visitNode(bindingTarget.objectAssignmentInitializer, visitor, isExpression)
|
||||
: bindingTarget.objectAssignmentInitializer;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@ namespace ts {
|
||||
return visitBinaryExpression(<BinaryExpression>node);
|
||||
}
|
||||
|
||||
Debug.fail("Unexpected node kind.");
|
||||
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
|
||||
}
|
||||
|
||||
function visitBinaryExpression(node: BinaryExpression): Expression {
|
||||
@@ -90,7 +90,7 @@ namespace ts {
|
||||
return createMathPow(left, right, /*location*/ node);
|
||||
}
|
||||
else {
|
||||
Debug.fail("Unexpected node kind.");
|
||||
Debug.fail(`Unexpected operator kind: ${formatSyntaxKind(node.operatorToken.kind)}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace ts {
|
||||
return visitJsxSelfClosingElement(<JsxSelfClosingElement>node);
|
||||
}
|
||||
|
||||
Debug.fail("Unexpected node kind.");
|
||||
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
|
||||
}
|
||||
|
||||
function transformJsxChildToExpression(node: JsxChild): Expression {
|
||||
@@ -52,7 +52,7 @@ namespace ts {
|
||||
return visitJsxSelfClosingElement(<JsxSelfClosingElement>node);
|
||||
}
|
||||
|
||||
Debug.fail("Unexpected node kind.");
|
||||
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
|
||||
}
|
||||
|
||||
function visitJsxElement(node: JsxElement) {
|
||||
@@ -85,14 +85,14 @@ namespace ts {
|
||||
properties = undefined;
|
||||
}
|
||||
|
||||
addNode(segments, transformJsxSpreadAttributeToExpression(attr), isExpression);
|
||||
addNode(segments, transformJsxSpreadAttributeToExpression(attr));
|
||||
}
|
||||
else {
|
||||
if (!properties) {
|
||||
properties = [];
|
||||
}
|
||||
|
||||
addNode(properties, transformJsxAttributeToObjectLiteralElement(attr), isObjectLiteralElement);
|
||||
addNode(properties, transformJsxAttributeToObjectLiteralElement(attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+108
-39
@@ -31,14 +31,17 @@ namespace ts {
|
||||
context.onBeforeEmitNode = onBeforeEmitNode;
|
||||
context.onAfterEmitNode = onAfterEmitNode;
|
||||
|
||||
let hasEnabledExpressionSubstitutionForAsyncMethodsWithSuper = false;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentNamespace: ModuleDeclaration;
|
||||
let currentNamespaceLocalName: Identifier;
|
||||
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
|
||||
let currentParent: Node;
|
||||
let currentNode: Node;
|
||||
let combinedNodeFlags: NodeFlags;
|
||||
let isRightmostExpression: boolean;
|
||||
|
||||
// This stack is is used to support substitutions when printing nodes.
|
||||
let hasEnabledExpressionSubstitutionForAsyncMethodsWithSuper = false;
|
||||
let superContainerStack: SuperContainer[];
|
||||
|
||||
return transformSourceFile;
|
||||
@@ -61,6 +64,7 @@ namespace ts {
|
||||
const savedCurrentScope = currentScope;
|
||||
const savedCurrentParent = currentParent;
|
||||
const savedCurrentNode = currentNode;
|
||||
const savedCombinedNodeFlags = combinedNodeFlags;
|
||||
const savedIsRightmostExpression = isRightmostExpression;
|
||||
onBeforeVisitNode(node);
|
||||
node = visitor(node);
|
||||
@@ -68,6 +72,7 @@ namespace ts {
|
||||
currentScope = savedCurrentScope;
|
||||
currentParent = savedCurrentParent;
|
||||
currentNode = savedCurrentNode;
|
||||
combinedNodeFlags = savedCombinedNodeFlags;
|
||||
isRightmostExpression = savedIsRightmostExpression;
|
||||
return node;
|
||||
}
|
||||
@@ -290,7 +295,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
// TypeScript type assertions are removed, but their subtrees are preserved.
|
||||
return visitNode((<TypeAssertion | AsExpression>node).expression, visitor, isExpression);
|
||||
return visitAssertionExpression(<AssertionExpression>node);
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
// TypeScript enum declarations do not exist in ES6 and must be rewritten.
|
||||
@@ -313,7 +318,7 @@ namespace ts {
|
||||
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
|
||||
|
||||
default:
|
||||
Debug.fail("Unexpected node.");
|
||||
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -326,6 +331,9 @@ namespace ts {
|
||||
function onBeforeVisitNode(node: Node) {
|
||||
currentParent = currentNode;
|
||||
currentNode = node;
|
||||
|
||||
combinedNodeFlags = combineNodeFlags(currentNode, currentParent, combinedNodeFlags);
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
@@ -357,7 +365,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
const modifiers = visitNodes(node.modifiers, visitor, isModifier);
|
||||
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
|
||||
const members = transformClassMembers(node, heritageClauses !== undefined);
|
||||
const members = transformClassMembers(node, firstOrUndefined(heritageClauses) !== undefined);
|
||||
let decoratedClassAlias: Identifier;
|
||||
|
||||
// emit name if
|
||||
@@ -744,7 +752,10 @@ namespace ts {
|
||||
|
||||
// End the lexical environment.
|
||||
addNodes(statements, endLexicalEnvironment());
|
||||
return createBlock(statements);
|
||||
return setMultiLine(
|
||||
createBlock(statements, constructor ? constructor.body : undefined),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -855,7 +866,17 @@ namespace ts {
|
||||
* @param receiver The receiver on which each property should be assigned.
|
||||
*/
|
||||
function generateInitializedPropertyStatements(node: ClassExpression | ClassDeclaration, properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
|
||||
return map(generateInitializedPropertyExpressions(node, properties, receiver), expressionToStatement);
|
||||
const statements: Statement[] = [];
|
||||
for (const property of properties) {
|
||||
statements.push(
|
||||
createStatement(
|
||||
transformInitializedProperty(node, property, receiver),
|
||||
/*location*/ property
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -868,8 +889,9 @@ namespace ts {
|
||||
function generateInitializedPropertyExpressions(node: ClassExpression | ClassDeclaration, properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
|
||||
const expressions: Expression[] = [];
|
||||
for (const property of properties) {
|
||||
expressions.push(transformInitializedProperty(node, property, receiver));
|
||||
expressions.push(transformInitializedProperty(node, property, receiver, /*location*/ property));
|
||||
}
|
||||
|
||||
return expressions;
|
||||
}
|
||||
|
||||
@@ -880,12 +902,13 @@ namespace ts {
|
||||
* @param property The property declaration.
|
||||
* @param receiver The object receiving the property assignment.
|
||||
*/
|
||||
function transformInitializedProperty(node: ClassExpression | ClassDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression) {
|
||||
function transformInitializedProperty(node: ClassExpression | ClassDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression, location?: TextRange) {
|
||||
const propertyName = visitPropertyNameOfClassElement(property);
|
||||
const initializer = visitNode(property.initializer, visitor, isExpression);
|
||||
return createAssignment(
|
||||
createMemberAccessForPropertyName(receiver, propertyName),
|
||||
initializer
|
||||
initializer,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1467,7 +1490,7 @@ namespace ts {
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.fail("Cannot serialize unexpected type node.");
|
||||
Debug.fail(`Unexpected node kind: ${formatSyntaxKind(node.kind)}.`);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2053,7 +2076,8 @@ namespace ts {
|
||||
return createStatement(
|
||||
inlineExpressions(
|
||||
map(variables, transformInitializedVariable)
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2113,7 +2137,10 @@ namespace ts {
|
||||
location = undefined;
|
||||
}
|
||||
|
||||
const namespaceMemberName = getNamespaceMemberName(node.name);
|
||||
const name = isNamespaceExport(node)
|
||||
? getNamespaceMemberName(node.name)
|
||||
: getSynthesizedNode(node.name);
|
||||
|
||||
currentNamespaceLocalName = getGeneratedNameForNode(node);
|
||||
addNode(statements,
|
||||
createStatement(
|
||||
@@ -2127,9 +2154,9 @@ namespace ts {
|
||||
)
|
||||
),
|
||||
[createLogicalOr(
|
||||
namespaceMemberName,
|
||||
name,
|
||||
createAssignment(
|
||||
namespaceMemberName,
|
||||
name,
|
||||
createObjectLiteral()
|
||||
)
|
||||
)]
|
||||
@@ -2143,7 +2170,7 @@ namespace ts {
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(node.name, namespaceMemberName)
|
||||
createVariableDeclaration(node.name, name)
|
||||
]),
|
||||
location
|
||||
)
|
||||
@@ -2229,12 +2256,20 @@ namespace ts {
|
||||
* @param node The await expression node.
|
||||
*/
|
||||
function visitAwaitExpression(node: AwaitExpression): Expression {
|
||||
const expression = createYield(
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
const expression = setOriginalNode(
|
||||
createYield(
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
|
||||
return isRightmostExpression ? expression : createParen(expression);
|
||||
return isRightmostExpression
|
||||
? expression
|
||||
: setOriginalNode(
|
||||
createParen(expression, /*location*/ node),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2265,11 +2300,29 @@ namespace ts {
|
||||
!(expression.kind === SyntaxKind.CallExpression && currentParent.kind === SyntaxKind.NewExpression) &&
|
||||
!(expression.kind === SyntaxKind.FunctionExpression && currentParent.kind === SyntaxKind.CallExpression) &&
|
||||
!(expression.kind === SyntaxKind.NumericLiteral && currentParent.kind === SyntaxKind.PropertyAccessExpression)) {
|
||||
return expression;
|
||||
return trackChildOfNotEmittedNode(node, expression, node.expression);
|
||||
}
|
||||
}
|
||||
|
||||
return createParen(expression, node);
|
||||
return setOriginalNode(
|
||||
createParen(expression, node),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
function visitAssertionExpression(node: AssertionExpression): Expression {
|
||||
const expression = visitNode((<TypeAssertion | AsExpression>node).expression, visitor, isExpression);
|
||||
return trackChildOfNotEmittedNode(node, expression, node.expression);
|
||||
}
|
||||
|
||||
function trackChildOfNotEmittedNode<T extends Node>(parent: Node, child: T, original: T) {
|
||||
if (!child.parent && !child.original) {
|
||||
child = cloneNode(child, child, child.flags, child.parent, original);
|
||||
}
|
||||
|
||||
setNodeEmitFlags(parent, NodeEmitFlags.IsNotEmittedNode);
|
||||
setNodeEmitFlags(child, NodeEmitFlags.EmitCommentsOfNotEmittedParent);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2305,10 +2358,14 @@ namespace ts {
|
||||
location = undefined;
|
||||
}
|
||||
|
||||
const name = isNamespaceExport(node)
|
||||
? getNamespaceMemberName(node.name)
|
||||
: getSynthesizedNode(node.name);
|
||||
|
||||
let moduleParam: Expression = createLogicalOr(
|
||||
getNamespaceMemberName(node.name),
|
||||
name,
|
||||
createAssignment(
|
||||
getNamespaceMemberName(node.name),
|
||||
name,
|
||||
createObjectLiteral([])
|
||||
)
|
||||
);
|
||||
@@ -2515,13 +2572,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getNamespaceMemberName(name: Identifier): Expression {
|
||||
name = getSynthesizedNode(name);
|
||||
return currentNamespaceLocalName
|
||||
? createPropertyAccess(currentNamespaceLocalName, name)
|
||||
: name
|
||||
return createPropertyAccess(currentNamespaceLocalName, getSynthesizedNode(name));
|
||||
}
|
||||
|
||||
function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration) {
|
||||
function getDeclarationName(node: ClassExpression | ClassDeclaration | FunctionDeclaration | EnumDeclaration) {
|
||||
return node.name ? getSynthesizedNode(node.name) : getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
@@ -2536,7 +2590,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function substituteExpression(node: Expression): Expression {
|
||||
node = previousExpressionSubstitution ? previousExpressionSubstitution(node) : node;
|
||||
node = previousExpressionSubstitution(node);
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return substituteExpressionIdentifier(<Identifier>node);
|
||||
@@ -2556,19 +2610,30 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteExpressionIdentifier(node: Identifier) {
|
||||
if (!nodeIsSynthesized(node) && resolver.getNodeCheckFlags(node) & NodeCheckFlags.BodyScopedClassBinding) {
|
||||
// Due to the emit for class decorators, any reference to the class from inside of the class body
|
||||
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
|
||||
// behavior of class names in ES6.
|
||||
const original = getOriginalNode(node);
|
||||
const declaration = resolver.getReferencedValueDeclaration(isIdentifier(original) ? original : node);
|
||||
if (declaration) {
|
||||
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
|
||||
if (classAlias) {
|
||||
return cloneNode(classAlias);
|
||||
function substituteExpressionIdentifier(node: Identifier): Expression {
|
||||
const original = getOriginalNode(node);
|
||||
if (isIdentifier(original)) {
|
||||
if (resolver.getNodeCheckFlags(original) & NodeCheckFlags.BodyScopedClassBinding) {
|
||||
// Due to the emit for class decorators, any reference to the class from inside of the class body
|
||||
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
|
||||
// behavior of class names in ES6.
|
||||
const declaration = resolver.getReferencedValueDeclaration(original);
|
||||
if (declaration) {
|
||||
const classAlias = currentDecoratedClassAliases[getNodeId(declaration)];
|
||||
if (classAlias) {
|
||||
return cloneNode(classAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const container = resolver.getReferencedExportContainer(original);
|
||||
if (container && container.kind === SyntaxKind.ModuleDeclaration) {
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(container),
|
||||
cloneNode(node),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -2652,6 +2717,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function onBeforeEmitNode(node: Node): void {
|
||||
previousOnAfterEmitNode(node);
|
||||
|
||||
const kind = node.kind;
|
||||
if (kind === SyntaxKind.ClassDeclaration && node.decorators) {
|
||||
currentDecoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAliases[getOriginalNodeId(node)];
|
||||
@@ -2673,6 +2740,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function onAfterEmitNode(node: Node): void {
|
||||
previousOnAfterEmitNode(node);
|
||||
|
||||
const kind = node.kind;
|
||||
if (kind === SyntaxKind.ClassDeclaration && node.decorators) {
|
||||
currentDecoratedClassAliases[getOriginalNodeId(node)] = undefined;
|
||||
|
||||
+21
-15
@@ -20,6 +20,7 @@ namespace ts {
|
||||
export interface TextRange {
|
||||
pos: number;
|
||||
end: number;
|
||||
/* @internal */ disableSourceMap?: boolean; // Whether a synthesized text range disables source maps for its contents (used by transforms).
|
||||
}
|
||||
|
||||
// token > SyntaxKind.Identifer => token is a keyword
|
||||
@@ -449,6 +450,7 @@ namespace ts {
|
||||
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
/* @internal */ original?: Node; // The original node if this is an updated node.
|
||||
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
|
||||
/* @internal */ jsDocComment?: JSDocComment; // JSDoc for the node, if it has any. Only for .js files.
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
@@ -1124,6 +1126,7 @@ namespace ts {
|
||||
// @kind(SyntaxKind.Block)
|
||||
export interface Block extends Statement {
|
||||
statements: NodeArray<Statement>;
|
||||
multiLine?: boolean;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.VariableStatement)
|
||||
@@ -2466,6 +2469,7 @@ namespace ts {
|
||||
allowSyntheticDefaultImports?: boolean;
|
||||
allowJs?: boolean;
|
||||
/* @internal */ stripInternal?: boolean;
|
||||
/* @internal */ experimentalTransforms?: boolean;
|
||||
|
||||
// Skip checking lib.d.ts to help speed up tests.
|
||||
/* @internal */ skipDefaultLibCheck?: boolean;
|
||||
@@ -2767,6 +2771,7 @@ namespace ts {
|
||||
ContainsParameterPropertyAssignments = 1 << 13,
|
||||
ContainsSpreadElementExpression = 1 << 14,
|
||||
ContainsComputedPropertyName = 1 << 15,
|
||||
ContainsBlockScopedBinding = 1 << 16,
|
||||
|
||||
// Assertions
|
||||
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
|
||||
@@ -2779,12 +2784,12 @@ namespace ts {
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
NodeExcludes = TypeScript | Jsx | ES7 | ES6,
|
||||
ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments,
|
||||
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments,
|
||||
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsParameterPropertyAssignments,
|
||||
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis,
|
||||
ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
|
||||
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
|
||||
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
MethodOrAccessorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
ClassExcludes = ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments,
|
||||
ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis,
|
||||
ModuleExcludes = ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = ContainsDecorators | ContainsComputedPropertyName,
|
||||
ArrayLiteralOrCallOrNewExcludes = ContainsSpreadElementExpression,
|
||||
@@ -2792,15 +2797,16 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export const enum NodeEmitFlags {
|
||||
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.
|
||||
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 emit on a single line.
|
||||
MultiLine = 1 << 7, // The contents of this node should be emit on multiple lines.
|
||||
AdviseOnEmitNode = 1 << 8, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
|
||||
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.
|
||||
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 emit on a single line.
|
||||
AdviseOnEmitNode = 1 << 7, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
|
||||
IsNotEmittedNode = 1 << 8, // Is a node that is not emitted but whose comments should be preserved if possible.
|
||||
EmitCommentsOfNotEmittedParent = 1 << 8, // Emits comments of missing parent nodes.
|
||||
}
|
||||
|
||||
/** Additional context provided to `visitEachChild` */
|
||||
@@ -2817,7 +2823,7 @@ namespace ts {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getEmitResolver(): EmitResolver;
|
||||
getNodeEmitFlags(node: Node): NodeEmitFlags;
|
||||
setNodeEmitFlags(node: Node, flags: NodeEmitFlags): void;
|
||||
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
|
||||
hoistFunctionDeclaration(node: FunctionDeclaration): void;
|
||||
hoistVariableDeclaration(node: Identifier): void;
|
||||
isUniqueName(name: string): boolean;
|
||||
|
||||
+122
-64
@@ -8,13 +8,6 @@ namespace ts {
|
||||
isNoDefaultLib?: boolean;
|
||||
}
|
||||
|
||||
export interface SynthesizedNode extends Node {
|
||||
leadingCommentRanges?: CommentRange[];
|
||||
trailingCommentRanges?: CommentRange[];
|
||||
startsOnNewLine?: boolean;
|
||||
disableSourceMap?: boolean;
|
||||
}
|
||||
|
||||
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
|
||||
const declarations = symbol.declarations;
|
||||
if (declarations) {
|
||||
@@ -330,8 +323,7 @@ namespace ts {
|
||||
export function isBlockScopedContainerTopLevel(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.SourceFile ||
|
||||
node.kind === SyntaxKind.ModuleDeclaration ||
|
||||
isFunctionLike(node) ||
|
||||
isFunctionBlock(node);
|
||||
isFunctionLike(node);
|
||||
}
|
||||
|
||||
export function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean {
|
||||
@@ -354,30 +346,41 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isBlockScope(node: Node, parentNode: Node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return true;
|
||||
|
||||
case SyntaxKind.Block:
|
||||
// function block is not considered block-scope container
|
||||
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
|
||||
return parentNode && !isFunctionLike(parentNode);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gets the nearest enclosing block scope container that has the provided node
|
||||
// as a descendant, that is not the provided node.
|
||||
export function getEnclosingBlockScopeContainer(node: Node): Node {
|
||||
let current = node.parent;
|
||||
while (current) {
|
||||
if (isFunctionLike(current)) {
|
||||
if (isBlockScope(current, current.parent)) {
|
||||
return current;
|
||||
}
|
||||
switch (current.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.CaseBlock:
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return current;
|
||||
case SyntaxKind.Block:
|
||||
// function block is not considered block-scope container
|
||||
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
|
||||
if (!isFunctionLike(current.parent)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
current = current.parent;
|
||||
}
|
||||
@@ -488,6 +491,19 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the flags of a node with the combined flags of its parent if they can be combined.
|
||||
*/
|
||||
export function combineNodeFlags(node: Node, parentNode: Node, previousNodeFlags: NodeFlags) {
|
||||
if ((node.kind === SyntaxKind.VariableDeclarationList && parentNode.kind === SyntaxKind.VariableStatement) ||
|
||||
(node.kind === SyntaxKind.VariableDeclaration && parentNode.kind === SyntaxKind.VariableDeclarationList) ||
|
||||
(node.kind === SyntaxKind.BindingElement)) {
|
||||
return node.flags | previousNodeFlags;
|
||||
}
|
||||
|
||||
return node.flags;
|
||||
}
|
||||
|
||||
// Returns the node flags for this node and all relevant parent nodes. This is done so that
|
||||
// nodes like variable declarations and binding elements can returned a view of their flags
|
||||
// that includes the modifiers from their container. i.e. flags like export/declare aren't
|
||||
@@ -1733,7 +1749,7 @@ namespace ts {
|
||||
return getOperatorPrecedence(expression.kind, operator, hasArguments);
|
||||
}
|
||||
|
||||
function getOperator(expression: Expression) {
|
||||
export function getOperator(expression: Expression) {
|
||||
if (expression.kind === SyntaxKind.BinaryExpression) {
|
||||
return (<BinaryExpression>expression).operatorToken.kind;
|
||||
}
|
||||
@@ -2318,26 +2334,33 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
|
||||
export function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], leadingSeparator: boolean, trailingSeparator: boolean, newLine: string,
|
||||
writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
|
||||
let emitLeadingSpace = !trailingSeparator;
|
||||
forEach(comments, comment => {
|
||||
if (emitLeadingSpace) {
|
||||
writer.write(" ");
|
||||
emitLeadingSpace = false;
|
||||
}
|
||||
writeComment(text, lineMap, writer, comment, newLine);
|
||||
if (comment.hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else if (trailingSeparator) {
|
||||
if (comments && comments.length > 0) {
|
||||
if (leadingSeparator) {
|
||||
writer.write(" ");
|
||||
}
|
||||
else {
|
||||
// Emit leading space to separate comment during next comment emit
|
||||
emitLeadingSpace = true;
|
||||
|
||||
let emitInterveningSeperator = false;
|
||||
for (const comment of comments) {
|
||||
if (emitInterveningSeperator) {
|
||||
writer.write(" ");
|
||||
emitInterveningSeperator = false;
|
||||
}
|
||||
|
||||
writeComment(text, lineMap, writer, comment, newLine);
|
||||
if (comment.hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else {
|
||||
emitInterveningSeperator = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (emitInterveningSeperator && trailingSeparator) {
|
||||
writer.write(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2394,7 +2417,7 @@ namespace ts {
|
||||
if (nodeLine >= lastCommentLine + 2) {
|
||||
// Valid detachedComments
|
||||
emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments);
|
||||
emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
|
||||
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end };
|
||||
}
|
||||
}
|
||||
@@ -2795,6 +2818,35 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function formatSyntaxKind(kind: SyntaxKind): string {
|
||||
const syntaxKindEnum = (<any>ts).SyntaxKind;
|
||||
if (syntaxKindEnum) {
|
||||
for (const name in syntaxKindEnum) {
|
||||
if (syntaxKindEnum[name] === kind) {
|
||||
return kind.toString() + " (" + name + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return kind.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export const enum TextRangeCollapse {
|
||||
CollapseToStart,
|
||||
CollapseToEnd,
|
||||
}
|
||||
|
||||
export function collapseTextRange(range: TextRange, collapse: TextRangeCollapse) {
|
||||
if (range.pos === range.end) {
|
||||
return range;
|
||||
}
|
||||
|
||||
return collapse === TextRangeCollapse.CollapseToStart
|
||||
? { pos: range.pos, end: range.end }
|
||||
: { pos: range.end, end: range.end };
|
||||
}
|
||||
|
||||
// Node tests
|
||||
//
|
||||
// All node tests in the following list should *not* reference parent pointers so that
|
||||
@@ -2812,6 +2864,10 @@ namespace ts {
|
||||
|
||||
// Literals
|
||||
|
||||
export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression {
|
||||
return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isLiteralKind(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
|
||||
}
|
||||
@@ -2905,6 +2961,10 @@ namespace ts {
|
||||
|
||||
// Type members
|
||||
|
||||
export function isMethodDeclaration(node: Node): node is MethodDeclaration {
|
||||
return node.kind === SyntaxKind.MethodDeclaration;
|
||||
}
|
||||
|
||||
export function isClassElement(node: Node): node is ClassElement {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Constructor
|
||||
@@ -2991,11 +3051,16 @@ namespace ts {
|
||||
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isSpreadElementExpression(node: Node): node is SpreadElementExpression {
|
||||
return node.kind === SyntaxKind.SpreadElementExpression;
|
||||
}
|
||||
|
||||
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
|
||||
function isLeftHandSideExpressionKind(kind: SyntaxKind) {
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.PropertyAccessExpression
|
||||
|| kind === SyntaxKind.ElementAccessExpression
|
||||
|| kind === SyntaxKind.NewExpression
|
||||
@@ -3021,11 +3086,8 @@ namespace ts {
|
||||
|| kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
return isLeftHandSideExpressionKind(node.kind);
|
||||
}
|
||||
|
||||
function isUnaryExpressionKind(kind: SyntaxKind): boolean {
|
||||
export function isUnaryExpression(node: Node): node is UnaryExpression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.PrefixUnaryExpression
|
||||
|| kind === SyntaxKind.PostfixUnaryExpression
|
||||
|| kind === SyntaxKind.DeleteExpression
|
||||
@@ -3033,14 +3095,11 @@ namespace ts {
|
||||
|| kind === SyntaxKind.VoidExpression
|
||||
|| kind === SyntaxKind.AwaitExpression
|
||||
|| kind === SyntaxKind.TypeAssertionExpression
|
||||
|| isLeftHandSideExpressionKind(kind);
|
||||
|| isLeftHandSideExpression(node);
|
||||
}
|
||||
|
||||
export function isUnaryExpression(node: Node): node is UnaryExpression {
|
||||
return isUnaryExpressionKind(node.kind);
|
||||
}
|
||||
|
||||
export function isExpressionKind(kind: SyntaxKind): boolean {
|
||||
export function isExpression(node: Node): node is Expression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ConditionalExpression
|
||||
|| kind === SyntaxKind.YieldExpression
|
||||
|| kind === SyntaxKind.ArrowFunction
|
||||
@@ -3048,11 +3107,7 @@ namespace ts {
|
||||
|| kind === SyntaxKind.SpreadElementExpression
|
||||
|| kind === SyntaxKind.AsExpression
|
||||
|| kind === SyntaxKind.OmittedExpression
|
||||
|| isUnaryExpressionKind(kind);
|
||||
}
|
||||
|
||||
export function isExpression(node: Node): node is Expression {
|
||||
return isExpressionKind(node.kind);
|
||||
|| isUnaryExpression(node);
|
||||
}
|
||||
|
||||
// Misc
|
||||
@@ -3264,9 +3319,12 @@ namespace ts {
|
||||
|
||||
// Property assignments
|
||||
|
||||
export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ShorthandPropertyAssignment;
|
||||
export function isPropertyAssignment(node: Node): node is PropertyAssignment {
|
||||
return node.kind === SyntaxKind.PropertyAssignment;
|
||||
}
|
||||
|
||||
export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
|
||||
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
|
||||
}
|
||||
|
||||
// Enum
|
||||
|
||||
+117
-45
@@ -19,6 +19,8 @@ namespace ts {
|
||||
|
||||
/** A callback used to lift a NodeArrayNode into a valid node. */
|
||||
lift?: (nodes: NodeArray<Node>) => Node;
|
||||
|
||||
parenthesize?: (value: Node, parentNode: Node) => Node;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -52,7 +54,7 @@ namespace ts {
|
||||
{ name: "modifiers", test: isModifier },
|
||||
{ name: "name", test: isBindingName },
|
||||
{ name: "type", test: isTypeNode, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.Decorator]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
@@ -108,34 +110,34 @@ namespace ts {
|
||||
[SyntaxKind.BindingElement]: [
|
||||
{ name: "propertyName", test: isPropertyName, optional: true },
|
||||
{ name: "name", test: isBindingName },
|
||||
{ name: "initializer", test: isExpression, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.ArrayLiteralExpression]: [
|
||||
{ name: "elements", test: isExpression },
|
||||
{ name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.ObjectLiteralExpression]: [
|
||||
{ name: "properties", test: isObjectLiteralElement },
|
||||
],
|
||||
[SyntaxKind.PropertyAccessExpression]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "name", test: isIdentifier },
|
||||
],
|
||||
[SyntaxKind.ElementAccessExpression]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "argumentExpression", test: isExpression },
|
||||
],
|
||||
[SyntaxKind.CallExpression]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "typeArguments", test: isTypeNode },
|
||||
{ name: "arguments", test: isExpression },
|
||||
],
|
||||
[SyntaxKind.NewExpression]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "typeArguments", test: isTypeNode },
|
||||
{ name: "arguments", test: isExpression },
|
||||
],
|
||||
[SyntaxKind.TaggedTemplateExpression]: [
|
||||
{ name: "tag", test: isLeftHandSideExpression },
|
||||
{ name: "tag", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "template", test: isTemplate },
|
||||
],
|
||||
[SyntaxKind.TypeAssertionExpression]: [
|
||||
@@ -163,26 +165,26 @@ namespace ts {
|
||||
{ name: "body", test: isConciseBody, lift: liftToBlock },
|
||||
],
|
||||
[SyntaxKind.DeleteExpression]: [
|
||||
{ name: "expression", test: isUnaryExpression },
|
||||
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
|
||||
],
|
||||
[SyntaxKind.TypeOfExpression]: [
|
||||
{ name: "expression", test: isUnaryExpression },
|
||||
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
|
||||
],
|
||||
[SyntaxKind.VoidExpression]: [
|
||||
{ name: "expression", test: isUnaryExpression },
|
||||
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
|
||||
],
|
||||
[SyntaxKind.AwaitExpression]: [
|
||||
{ name: "expression", test: isUnaryExpression },
|
||||
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
|
||||
],
|
||||
[SyntaxKind.PrefixUnaryExpression]: [
|
||||
{ name: "operand", test: isUnaryExpression },
|
||||
{ name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
|
||||
],
|
||||
[SyntaxKind.PostfixUnaryExpression]: [
|
||||
{ name: "operand", test: isLeftHandSideExpression },
|
||||
{ name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand },
|
||||
],
|
||||
[SyntaxKind.BinaryExpression]: [
|
||||
{ name: "left", test: isExpression },
|
||||
{ name: "right", test: isExpression },
|
||||
{ name: "left", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, true) },
|
||||
{ name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false) },
|
||||
],
|
||||
[SyntaxKind.ConditionalExpression]: [
|
||||
{ name: "condition", test: isExpression },
|
||||
@@ -197,7 +199,7 @@ namespace ts {
|
||||
{ name: "expression", test: isExpression, optional: true },
|
||||
],
|
||||
[SyntaxKind.SpreadElementExpression]: [
|
||||
{ name: "expression", test: isExpression },
|
||||
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.ClassExpression]: [
|
||||
{ name: "decorators", test: isDecorator },
|
||||
@@ -208,7 +210,7 @@ namespace ts {
|
||||
{ name: "members", test: isClassElement },
|
||||
],
|
||||
[SyntaxKind.ExpressionWithTypeArguments]: [
|
||||
{ name: "expression", test: isLeftHandSideExpression },
|
||||
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
|
||||
{ name: "typeArguments", test: isTypeNode },
|
||||
],
|
||||
[SyntaxKind.AsExpression]: [
|
||||
@@ -228,7 +230,7 @@ namespace ts {
|
||||
{ name: "declarationList", test: isVariableDeclarationList },
|
||||
],
|
||||
[SyntaxKind.ExpressionStatement]: [
|
||||
{ name: "expression", test: isExpression },
|
||||
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement },
|
||||
],
|
||||
[SyntaxKind.IfStatement]: [
|
||||
{ name: "expression", test: isExpression },
|
||||
@@ -291,7 +293,7 @@ namespace ts {
|
||||
[SyntaxKind.VariableDeclaration]: [
|
||||
{ name: "name", test: isBindingName },
|
||||
{ name: "type", test: isTypeNode, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.VariableDeclarationList]: [
|
||||
{ name: "declarations", test: isVariableDeclaration },
|
||||
@@ -420,7 +422,7 @@ namespace ts {
|
||||
],
|
||||
[SyntaxKind.PropertyAssignment]: [
|
||||
{ name: "name", test: isPropertyName },
|
||||
{ name: "initializer", test: isExpression },
|
||||
{ name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.ShorthandPropertyAssignment]: [
|
||||
{ name: "name", test: isIdentifier },
|
||||
@@ -428,7 +430,7 @@ namespace ts {
|
||||
],
|
||||
[SyntaxKind.EnumMember]: [
|
||||
{ name: "name", test: isPropertyName },
|
||||
{ name: "initializer", test: isExpression, optional: true },
|
||||
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
|
||||
],
|
||||
[SyntaxKind.SourceFile]: [
|
||||
{ name: "statements", test: isStatement },
|
||||
@@ -492,7 +494,6 @@ namespace ts {
|
||||
|
||||
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.");
|
||||
aggregateTransformFlags(visited);
|
||||
visited.original = node;
|
||||
return <T>visited;
|
||||
}
|
||||
|
||||
@@ -541,14 +542,14 @@ namespace ts {
|
||||
aggregateTransformFlags(visited);
|
||||
}
|
||||
|
||||
addNode(updated, visited, test);
|
||||
addNodeWorker(updated, visited, /*addOnNewLine*/ undefined, test);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated !== undefined) {
|
||||
return <TArray>(isModifiersArray(nodes)
|
||||
? createModifiersArray(updated, nodes)
|
||||
: createNodeArray(updated, nodes));
|
||||
: setHasTrailingComma(createNodeArray(updated, nodes), nodes.hasTrailingComma));
|
||||
}
|
||||
|
||||
return nodes;
|
||||
@@ -577,21 +578,27 @@ namespace ts {
|
||||
|
||||
const edgeTraversalPath = nodeEdgeTraversalMap[node.kind];
|
||||
if (edgeTraversalPath) {
|
||||
let modifiers: NodeFlags;
|
||||
for (const edge of edgeTraversalPath) {
|
||||
const value = <Node | NodeArray<Node>>node[edge.name];
|
||||
if (value !== undefined) {
|
||||
const visited = visitEdge(edge, value, visitor);
|
||||
if (visited && isArray(visited) && isModifiersArray(visited)) {
|
||||
modifiers = visited.flags;
|
||||
}
|
||||
|
||||
if (updated !== undefined || visited !== value) {
|
||||
if (updated === undefined) {
|
||||
updated = cloneNode(node, /*location*/ node, node.flags & ~NodeFlags.Modifier, /*parent*/ undefined, /*original*/ node);
|
||||
}
|
||||
|
||||
if (visited && isArray(visited) && isModifiersArray(visited)) {
|
||||
updated[edge.name] = visited;
|
||||
updated.flags |= visited.flags;
|
||||
if (modifiers) {
|
||||
updated.flags |= modifiers;
|
||||
modifiers = undefined;
|
||||
}
|
||||
else {
|
||||
updated[edge.name] = visited;
|
||||
|
||||
if (visited !== value) {
|
||||
setEdgeValue(updated, edge, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -617,6 +624,17 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of an edge, adjusting the value as necessary for cases such as expression precedence.
|
||||
*/
|
||||
function setEdgeValue(parentNode: Node & Map<any>, edge: NodeEdge, value: Node | NodeArray<Node>) {
|
||||
if (value && edge.parenthesize && !isArray(value)) {
|
||||
value = parenthesizeEdge(<Node>value, parentNode, edge.parenthesize, edge.test);
|
||||
}
|
||||
|
||||
parentNode[edge.name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a node edge.
|
||||
*
|
||||
@@ -627,7 +645,31 @@ namespace ts {
|
||||
function visitEdge(edge: NodeEdge, value: Node | NodeArray<Node>, visitor: (node: Node) => Node) {
|
||||
return isArray(value)
|
||||
? visitNodes(<NodeArray<Node>>value, visitor, edge.test, /*start*/ undefined, /*count*/ undefined)
|
||||
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
|
||||
: visitNode(<Node>value, visitor, !edge.parenthesize ? edge.test : undefined, edge.optional, edge.lift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies parentheses to a node to ensure the correct precedence.
|
||||
*/
|
||||
function parenthesizeEdge(node: Node, parentNode: Node, parenthesize: (node: Node, parentNode: Node) => Node, test: (node: Node) => boolean) {
|
||||
node = parenthesize(node, parentNode);
|
||||
Debug.assert(test === undefined || test(node), "Unexpected node kind after visit.");
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens an array of nodes that could contain NodeArrayNodes.
|
||||
*/
|
||||
export function flattenNodes<T extends Node>(nodes: OneOrMore<T>[]): T[] {
|
||||
let result: T[];
|
||||
if (nodes) {
|
||||
result = [];
|
||||
for (const node of nodes) {
|
||||
addNode(result, node);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -635,18 +677,9 @@ namespace ts {
|
||||
*
|
||||
* @param to The destination array.
|
||||
* @param from The source Node or NodeArrayNode.
|
||||
* @param test The node test used to validate each node.
|
||||
*/
|
||||
export function addNode<T extends Node>(to: T[], from: OneOrMore<T>, test?: (node: Node) => boolean) {
|
||||
if (to && from) {
|
||||
if (isNodeArrayNode(from)) {
|
||||
addNodes(to, from.nodes, test);
|
||||
}
|
||||
else {
|
||||
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
|
||||
to.push(from);
|
||||
}
|
||||
}
|
||||
export function addNode<T extends Node>(to: T[], from: OneOrMore<T>, startOnNewLine?: boolean) {
|
||||
addNodeWorker(to, from, startOnNewLine, /*test*/ undefined)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -654,12 +687,51 @@ namespace ts {
|
||||
*
|
||||
* @param to The destination NodeArray.
|
||||
* @param from The source array of Node or NodeArrayNode.
|
||||
* @param test The node test used to validate each node.
|
||||
*/
|
||||
export function addNodes<T extends Node>(to: T[], from: OneOrMore<T>[], test?: (node: Node) => boolean) {
|
||||
export function addNodes<T extends Node>(to: T[], from: OneOrMore<T>[], startOnNewLine?: boolean) {
|
||||
addNodesWorker(to, from, startOnNewLine, /*test*/ undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a node to an array on a new line.
|
||||
*
|
||||
* @param to The destination array.
|
||||
* @param from The source Node or NodeArrayNode.
|
||||
*/
|
||||
export function addLine<T extends Node>(to: T[], from: OneOrMore<T>) {
|
||||
addNodeWorker(to, from, /*addOnNewLine*/ true, /*test*/ undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an array of nodes to an array on new lines.
|
||||
*
|
||||
* @param to The destination NodeArray.
|
||||
* @param from The source array of Node or NodeArrayNode.
|
||||
*/
|
||||
export function addLines<T extends Node>(to: T[], from: OneOrMore<T>[]) {
|
||||
addNodesWorker(to, from, /*addOnNewLine*/ true, /*test*/ undefined);
|
||||
}
|
||||
|
||||
function addNodeWorker<T extends Node>(to: T[], from: OneOrMore<T>, addOnNewLine: boolean, test: (node: Node) => boolean) {
|
||||
if (to && from) {
|
||||
if (isNodeArrayNode(from)) {
|
||||
addNodesWorker(to, from.nodes, addOnNewLine, test);
|
||||
}
|
||||
else {
|
||||
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
|
||||
if (addOnNewLine) {
|
||||
startOnNewLine(from);
|
||||
}
|
||||
|
||||
to.push(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addNodesWorker<T extends Node>(to: T[], from: OneOrMore<T>[], addOnNewLine: boolean, test: (node: Node) => boolean) {
|
||||
if (to && from) {
|
||||
for (const node of from) {
|
||||
addNode(to, node, test);
|
||||
addNodeWorker(to, node, addOnNewLine, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user