Merge branch 'transforms-printer' into transforms-transformer-ts

This commit is contained in:
Ron Buckton 2016-02-22 16:35:57 -08:00
commit 0a325ee04c
19 changed files with 997 additions and 481 deletions

View file

@ -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);

View file

@ -1798,7 +1798,7 @@ namespace ts {
* @param node The node to analyze
* @param subtreeFlags Transform flags computed for this node's subtree
*/
export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) {
export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags {
// Ambient nodes are TypeScript syntax and the flags of their subtree are ignored.
if (node.flags & NodeFlags.Ambient) {
return (node.transformFlags = TransformFlags.AssertTypeScript)
@ -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.

View file

@ -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
}
];

View file

@ -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) {

View file

@ -130,11 +130,12 @@ namespace ts {
return -1;
}
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
export function countWhere<T>(array: T[], predicate: (x: T, i: number) => boolean): number {
let count = 0;
if (array) {
for (const v of array) {
if (predicate(v)) {
for (let i = 0; i < array.length; i++) {
const v = array[i];
if (predicate(v, i)) {
count++;
}
}
@ -170,7 +171,10 @@ namespace ts {
return result;
}
export function flatMap<T, U>(array: T[], f: (x: T, i: number) => U[]): U[] {
/**
* Maps an array. If the mapped value is an array, it is spread into the result.
*/
export function flatMap<T, U>(array: T[], f: (x: T, i: number) => U | U[]): U[] {
let result: U[];
if (array) {
result = [];
@ -178,7 +182,9 @@ namespace ts {
const v = array[i];
const ar = f(v, i);
if (ar) {
result = result.concat(ar);
// We cast to <U> here to leverage the behavior of Array#concat
// which will append a single value here.
result = result.concat(<U[]>ar);
}
}
}
@ -191,18 +197,6 @@ namespace ts {
return [...array1, ...array2];
}
export function append<T>(array: T[], value: T): T[] {
if (value === undefined) return array;
if (!array || !array.length) return [value];
return [...array, value];
}
export function prepend<T>(array: T[], value: T): T[] {
if (value === undefined) return array;
if (!array || !array.length) return [value];
return [value, ...array];
}
export function deduplicate<T>(array: T[]): T[] {
let result: T[];
if (array) {
@ -216,6 +210,27 @@ namespace ts {
return result;
}
/**
* Compacts an array, removing any falsey elements.
*/
export function compact<T>(array: T[]): T[] {
let result: T[];
if (array) {
for (let i = 0; i < array.length; i++) {
const v = array[i];
if (result || !v) {
if (!result) {
result = array.slice(0, i);
}
if (v) {
result.push(v);
}
}
}
}
return result || array;
}
export function sum(array: any[], prop: string): number {
let result = 0;
for (const v of array) {
@ -292,9 +307,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 +323,7 @@ namespace ts {
result = initial;
}
while (pos < count) {
result = f(result, array[pos]);
result = f(result, array[pos], pos);
pos++;
}
return result;
@ -317,9 +332,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 +347,7 @@ namespace ts {
result = initial;
}
while (pos >= 0) {
result = f(result, array[pos]);
result = f(result, array[pos], pos);
pos--;
}
return result;

View file

@ -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;

View file

@ -1919,7 +1919,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (multiLine) {
decreaseIndent();
writeLine();
}
write(")");
@ -2246,6 +2245,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 +2701,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 +3318,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 +4335,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 +5353,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 +5394,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 +5420,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 +7975,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 +7987,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 +8002,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 +8024,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) {

View file

@ -22,7 +22,7 @@ namespace ts {
return node;
}
export function createNodeArray<T extends Node>(elements?: T[], location?: TextRange): NodeArray<T> {
export function createNodeArray<T extends Node>(elements?: T[], location?: TextRange, hasTrailingComma?: boolean): NodeArray<T> {
if (elements) {
if (isNodeArray(elements)) {
return elements;
@ -42,6 +42,10 @@ namespace ts {
array.end = -1;
}
if (hasTrailingComma) {
array.hasTrailingComma = true;
}
array.arrayKind = ArrayKind.NodeArray;
return array;
}
@ -92,7 +96,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;
}
@ -145,6 +149,13 @@ namespace ts {
return clone;
}
/**
* Creates a shallow, memberwise clone of a node for mutation.
*/
export function getMutableNode<T extends Node>(node: T): T {
return cloneNode<T>(node, node, node.flags, node.parent, node);
}
export function createNodeArrayNode<T extends Node>(elements: T[]): NodeArrayNode<T> {
const node = <NodeArrayNode<T>>createSynthesizedNode(SyntaxKind.NodeArrayNode);
node.nodes = createNodeArray(elements);
@ -153,20 +164,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 +214,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 +278,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;
@ -279,7 +290,6 @@ namespace ts {
return node;
}
// Expression
export function createArrayLiteral(elements?: Expression[]) {
@ -288,8 +298,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 +326,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 +364,27 @@ 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 createPrefix(operator: SyntaxKind, operand: Expression, location?: TextRange) {
const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression, location);
node.operator = operator;
node.operand = parenthesizePrefixOperand(operand);
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 +473,72 @@ 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 createForOf(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange) {
const node = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, 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;
}
@ -514,20 +603,30 @@ namespace ts {
return node;
}
// Property assignments
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;
}
// 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);
}
@ -536,8 +635,28 @@ 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 createLogicalNot(operand: Expression) {
return createPrefix(SyntaxKind.ExclamationToken, operand);
}
export function createVoidZero() {
@ -556,6 +675,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) {
@ -565,6 +706,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"),
@ -573,8 +721,51 @@ namespace ts {
);
}
export function createJsxSpread(reactNamespace: string, segments: Expression[]) {
return createCall(
createPropertyAccess(
createIdentifier(reactNamespace || "React"),
"__spread"
),
segments
);
}
export function createJsxCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[]): LeftHandSideExpression {
const argumentsList = [tagName];
if (props) {
argumentsList.push(props);
}
if (children && children.length > 0) {
if (!props) {
argumentsList.push(createNull());
}
addRange(argumentsList, children);
}
return createCall(
createPropertyAccess(
createIdentifier(reactNamespace || "React"),
"createElement"
),
argumentsList
);
}
// Helpers
export function createExtendsHelper(name: Identifier) {
return createCall(
createIdentifier("__extends"),
[
name,
createIdentifier("_super")
]
);
}
export function createParamHelper(expression: Expression, parameterOffset: number) {
return createCall(
createIdentifier("__param"),
@ -628,6 +819,63 @@ namespace ts {
);
}
export function createHasOwnProperty(target: LeftHandSideExpression, propertyName: Expression) {
return createCall(
createPropertyAccess(target, "hasOwnProperty"),
[propertyName]
);
}
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) {
property.startsOnNewLine = true;
}
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"),
@ -643,7 +891,7 @@ namespace ts {
target,
createIdentifier("name")
)
)
);
}
function createSeti(target: LeftHandSideExpression) {
@ -796,8 +1044,15 @@ 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
/**
* Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended
* order of operations.
@ -807,11 +1062,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;
@ -925,11 +1176,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:
//
@ -938,38 +1185,90 @@ 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;
}
/**
* Skips past any TypeAssertionExpression or AsExpression nodes to their inner expression.
*
* @param node The expression node.
*/
function skipAssertions(node: Expression) {
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
node = (<AssertionExpression>node).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;
}
export function startOnNewLine<T extends Node>(node: T): T {
(<SynthesizedNode>node).startsOnNewLine = true;
node.startsOnNewLine = true;
return node;
}

View file

@ -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);
}

View file

@ -119,13 +119,30 @@ 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,
getTrailingComments,
getTrailingCommentsOfPosition,
emitLeadingComments,
emitTrailingComments,
emitDetachedComments
} = comments;
let context: TransformationContext;
let startLexicalEnvironment: () => void;
@ -198,7 +215,7 @@ const _super = (function (geti, seti) {
onAfterEmitNode = undefined;
isUniqueName = undefined;
temporaryVariables = undefined;
tempFlags = 0;
tempFlags = TempFlags.Auto;
currentSourceFile = undefined;
currentText = undefined;
extendsEmitted = false;
@ -233,14 +250,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 +278,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 +394,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 +410,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 +418,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 +537,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 +665,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 +765,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 +779,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 +809,10 @@ const _super = (function (geti, seti) {
write(";");
}
function emitSemicolonClassElement(node: SemicolonClassElement) {
write(";");
}
//
// Types
//
@ -851,6 +879,10 @@ const _super = (function (geti, seti) {
write(")");
}
function emitThisType(node: ThisTypeNode) {
write("this");
}
//
// Binding patterns
//
@ -896,7 +928,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 +939,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 +1030,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 +1199,10 @@ const _super = (function (geti, seti) {
write(";");
}
function emitEmptyStatement(node: EmptyStatement) {
write(";");
}
function emitExpressionStatement(node: ExpressionStatement) {
emitExpression(node.expression);
write(";");
@ -1353,25 +1370,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 +1407,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 +1719,8 @@ const _super = (function (geti, seti) {
write("case ");
emitExpression(node.expression);
write(":");
debugger;
emitCaseOrDefaultClauseStatements(node, node.statements);
}
@ -1804,7 +1837,11 @@ const _super = (function (geti, seti) {
}
}
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean) {
/**
* Emits any prologue directives at the start of a Statement list, returning the
* number of prologue directives written to the output.
*/
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number {
for (let i = 0; i < statements.length; i++) {
if (isPrologueDirective(statements[i])) {
if (startWithNewLine || i > 0) {
@ -2051,8 +2088,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 +2115,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 +2222,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 +2264,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 +2289,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 +2321,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 +2336,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 +2363,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) {
@ -2407,6 +2466,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 +2484,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 +2493,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,

View file

@ -968,7 +968,8 @@ namespace ts {
const start = new Date().getTime();
const emitResult = emitFiles(
const fileEmitter = options.experimentalTransforms ? printFiles : emitFiles;
const emitResult = fileEmitter(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile);

View file

@ -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();
}

View file

@ -1,50 +1,15 @@
/// <reference path="visitor.ts" />
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/es7.ts" />
/// <reference path="transformers/es6.ts" />
/// <reference path="transformers/module/module.ts" />
/// <reference path="transformers/module/system.ts" />
/// <reference path="transformers/module/es6.ts" />
/* @internal */
namespace ts {
const moduleTransformerMap: Map<Transformer> = {
[ModuleKind.ES6]: transformES6Module,
[ModuleKind.System]: transformSystemModule,
[ModuleKind.AMD]: transformModule,
[ModuleKind.CommonJS]: transformModule,
[ModuleKind.UMD]: transformModule,
[ModuleKind.None]: transformModule
};
const enum SyntaxKindFeatureFlags {
ExpressionSubstitution = 1 << 0,
EmitNotifications = 1 << 1,
}
export function getTransformers(compilerOptions: CompilerOptions) {
const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const transformers: Transformer[] = [];
transformers.push(transformTypeScript);
transformers.push(moduleTransformerMap[moduleKind]);
if (jsx === JsxEmit.React) {
transformers.push(transformJsx);
}
if (languageVersion < ScriptTarget.ES7) {
transformers.push(transformES7);
}
if (languageVersion < ScriptTarget.ES6) {
transformers.push(transformES6);
}
// TODO(rbuckton): Add transformers
return transformers;
}
@ -63,7 +28,6 @@ namespace ts {
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentStackOffset = 0;
let hoistedVariableDeclarations: VariableDeclaration[];
let hoistedFunctionDeclarations: FunctionDeclaration[];
@ -84,8 +48,12 @@ namespace ts {
hoistFunctionDeclaration,
startLexicalEnvironment,
endLexicalEnvironment,
identifierSubstitution: node => node,
expressionSubstitution: node => node,
enableExpressionSubstitution,
isExpressionSubstitutionEnabled,
onBeforeEmitNode: node => { },
onAfterEmitNode: node => { },
enableEmitNotification,
isEmitNotificationEnabled,
};
@ -148,8 +116,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;
}
/**
@ -317,12 +286,17 @@ namespace ts {
}
if (hoistedVariableDeclarations) {
statements = append(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(hoistedVariableDeclarations)
)
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(hoistedVariableDeclarations)
);
if (!statements) {
statements = [statement];
}
else {
statements.push(statement);
}
}
}

View file

@ -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;

View file

@ -1772,7 +1772,7 @@ namespace ts {
*
* @param node The function node.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): OneOrMore<Statement> {
function visitFunctionDeclaration(node: FunctionDeclaration): OneOrMany<Statement> {
if (shouldElideFunctionLikeDeclaration(node)) {
return undefined;
}
@ -2389,7 +2389,7 @@ namespace ts {
*
* @param node The import equals declaration node.
*/
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): OneOrMore<Statement> {
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): OneOrMany<Statement> {
Debug.assert(!isExternalModuleImportEqualsDeclaration(node));
if (shouldElideImportEqualsDeclaration(node)) {
return undefined;

View file

@ -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>;
/*@internal*/ 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;
@ -2508,10 +2512,8 @@ namespace ts {
ES3 = 0,
ES5 = 1,
ES6 = 2,
ES7 = 3,
ES2015 = ES6,
ES2016 = ES7,
Latest = ES7,
Latest = ES6,
}
export const enum LanguageVariant {
@ -2767,6 +2769,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 +2782,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 +2795,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 +2821,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;

View file

@ -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) {
@ -180,6 +173,10 @@ namespace ts {
return node.pos;
}
export function isDefined(value: any): boolean {
return value !== undefined;
}
// Returns true if this node is missing from the actual source code. A 'missing' node is different
// from 'undefined/defined'. When a node is undefined (which can happen for optional nodes
// in the tree), it is definitely missing. However, a node may be defined, but still be
@ -1729,7 +1726,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;
}
@ -2314,26 +2311,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(" ");
}
}
}
/**
@ -2390,7 +2394,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 };
}
}
@ -2729,6 +2733,21 @@ namespace ts {
return carriageReturnLineFeed;
}
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 };
}
/**
* Tests whether a node and its subtree is simple enough to have its position
* information ignored when emitting source maps in a destructuring assignment.
@ -2808,6 +2827,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;
}
@ -2901,6 +2924,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
@ -2987,11 +3014,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
@ -3017,11 +3049,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
@ -3029,14 +3058,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
@ -3044,11 +3070,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
@ -3237,6 +3259,10 @@ namespace ts {
|| kind === SyntaxKind.JsxSpreadAttribute;
}
export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute {
return node.kind === SyntaxKind.JsxSpreadAttribute;
}
// Clauses
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
@ -3256,9 +3282,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

View file

@ -2,7 +2,7 @@
/* @internal */
namespace ts {
export type OneOrMore<T extends Node> = T | NodeArrayNode<T>;
export type OneOrMany<T extends Node> = T | NodeArrayNode<T>;
/**
* Describes an edge of a Node, used when traversing a syntax tree.
@ -19,6 +19,9 @@ namespace ts {
/** A callback used to lift a NodeArrayNode into a valid node. */
lift?: (nodes: NodeArray<Node>) => Node;
/** A callback used to parenthesize a node to preserve the intended order of operations. */
parenthesize?: (value: Node, parentNode: Node) => Node;
};
/**
@ -52,7 +55,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 +111,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 +166,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 +200,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 +211,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 +231,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 +294,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 +423,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 +431,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 },
@ -530,7 +533,7 @@ namespace ts {
// Visit each original node.
for (let i = 0; i < count; i++) {
const node = nodes[i + start];
const visited = node && <OneOrMore<T>>visitor(node);
const visited = node && <OneOrMany<T>>visitor(node);
if (updated !== undefined || visited === undefined || visited !== node) {
if (updated === undefined) {
// Ensure we have a copy of `nodes`, up to the current index.
@ -541,14 +544,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));
: createNodeArray(updated, nodes, nodes.hasTrailingComma));
}
return nodes;
@ -577,21 +580,28 @@ 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);
updated = getMutableNode(node);
updated.flags &= ~NodeFlags.Modifier;
}
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);
}
}
}
@ -630,6 +640,26 @@ namespace ts {
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
}
/**
* 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;
}
/**
* 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;
}
/**
* Appends a node to an array.
*
@ -637,16 +667,8 @@ namespace ts {
* @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: OneOrMany<T>, startOnNewLine?: boolean) {
addNodeWorker(to, from, startOnNewLine, /*test*/ undefined);
}
/**
@ -656,10 +678,30 @@ namespace ts {
* @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: OneOrMany<T>[], startOnNewLine?: boolean) {
addNodesWorker(to, from, startOnNewLine, /*test*/ undefined);
}
function addNodeWorker<T extends Node>(to: T[], from: OneOrMany<T>, startOnNewLine: boolean, test: (node: Node) => boolean) {
if (to && from) {
if (isNodeArrayNode(from)) {
addNodesWorker(to, from.nodes, startOnNewLine, test);
}
else {
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
if (startOnNewLine) {
from.startsOnNewLine = true;
}
to.push(from);
}
}
}
function addNodesWorker<T extends Node>(to: T[], from: OneOrMany<T>[], startOnNewLine: boolean, test: (node: Node) => boolean) {
if (to && from) {
for (const node of from) {
addNode(to, node, test);
addNodeWorker(to, node, startOnNewLine, test);
}
}
}
@ -824,7 +866,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
function liftToBlock(nodes: NodeArray<Node>) {
export function liftToBlock(nodes: NodeArray<Node>) {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return createBlock(<NodeArray<Statement>>nodes);
}

View file

@ -1,54 +1,54 @@
/**
* Declaration module describing the TypeScript Server protocol
/**
* Declaration module describing the TypeScript Server protocol
*/
declare namespace ts.server.protocol {
/**
* A TypeScript Server message
/**
* A TypeScript Server message
*/
export interface Message {
/**
* Sequence number of the message
/**
* Sequence number of the message
*/
seq: number;
/**
* One of "request", "response", or "event"
* One of "request", "response", or "event"
*/
type: string;
}
/**
* Client-initiated request message
/**
* Client-initiated request message
*/
export interface Request extends Message {
/**
* The command to execute
* The command to execute
*/
command: string;
/**
* Object containing arguments for the command
/**
* Object containing arguments for the command
*/
arguments?: any;
}
/**
* Request to reload the project structure for all the opened files
* Request to reload the project structure for all the opened files
*/
export interface ReloadProjectsRequest extends Message {
}
/**
* Server-initiated event message
/**
* Server-initiated event message
*/
export interface Event extends Message {
/**
* Name of event
/**
* Name of event
*/
event: string;
/**
* Event-specific information
/**
* Event-specific information
*/
body?: any;
}
@ -62,18 +62,18 @@ declare namespace ts.server.protocol {
*/
request_seq: number;
/**
* Outcome of the request.
/**
* Outcome of the request.
*/
success: boolean;
/**
/**
* The command requested.
*/
command: string;
/**
* Contains error message if success === false.
/**
* Contains error message if success === false.
*/
message?: string;
@ -83,7 +83,7 @@ declare namespace ts.server.protocol {
body?: any;
}
/**
/**
* Arguments for FileRequest messages.
*/
export interface FileRequestArgs {
@ -93,7 +93,7 @@ declare namespace ts.server.protocol {
file: string;
}
/**
/**
* Arguments for ProjectInfoRequest request.
*/
export interface ProjectInfoRequestArgs extends FileRequestArgs {
@ -110,7 +110,7 @@ declare namespace ts.server.protocol {
arguments: ProjectInfoRequestArgs;
}
/**
/**
* Response message body for "projectInfo" request
*/
export interface ProjectInfo {
@ -125,7 +125,7 @@ declare namespace ts.server.protocol {
fileNames?: string[];
}
/**
/**
* Response message for "projectInfo" request
*/
export interface ProjectInfoResponse extends Response {
@ -144,12 +144,12 @@ declare namespace ts.server.protocol {
* (file, line, character offset), where line and character offset are 1-based.
*/
export interface FileLocationRequestArgs extends FileRequestArgs {
/**
/**
* The line number for the request (1-based).
*/
line: number;
/**
/**
* The character offset (on the line) for the request (1-based).
*/
offset: number;
@ -216,7 +216,7 @@ declare namespace ts.server.protocol {
* Object found in response messages defining a span of text in a specific source file.
*/
export interface FileSpan extends TextSpan {
/**
/**
* File containing text span.
*/
file: string;
@ -300,14 +300,14 @@ declare namespace ts.server.protocol {
*/
lineText: string;
/**
/**
* True if reference is a write location, false otherwise.
*/
isWriteAccess: boolean;
}
/**
* The body of a "references" response message.
* The body of a "references" response message.
*/
export interface ReferencesResponseBody {
/**
@ -325,7 +325,7 @@ declare namespace ts.server.protocol {
*/
symbolStartOffset: number;
/**
/**
* The full display name of the symbol.
*/
symbolDisplayString: string;
@ -355,7 +355,7 @@ declare namespace ts.server.protocol {
}
/**
* Information about the item to be renamed.
* Information about the item to be renamed.
*/
export interface RenameInfo {
/**
@ -373,7 +373,7 @@ declare namespace ts.server.protocol {
*/
displayName: string;
/**
/**
* Full display name of item to be renamed.
*/
fullDisplayName: string;
@ -383,7 +383,7 @@ declare namespace ts.server.protocol {
*/
kind: string;
/**
/**
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
@ -469,7 +469,7 @@ declare namespace ts.server.protocol {
placeOpenBraceOnNewLineForControlBlocks?: boolean;
/** Index operator */
[key: string] : string | number | boolean;
[key: string]: string | number | boolean;
}
/**
@ -477,7 +477,7 @@ declare namespace ts.server.protocol {
*/
export interface ConfigureRequestArguments {
/**
/**
* Information about the host, for example 'Emacs 24.4' or
* 'Sublime Text version 3075'
*/
@ -495,7 +495,7 @@ declare namespace ts.server.protocol {
}
/**
* Configure request; value of command field is "configure". Specifies
* Configure request; value of command field is "configure". Specifies
* host information, such as host type, tab size, and indent size.
*/
export interface ConfigureRequest extends Request {
@ -514,8 +514,8 @@ declare namespace ts.server.protocol {
*/
export interface OpenRequestArgs extends FileRequestArgs {
/**
* Used when a version of the file content is known to be more up to date than the one on disk.
* Then the known content will be used upon opening instead of the disk copy
* Used when a version of the file content is known to be more up to date than the one on disk.
* Then the known content will be used upon opening instead of the disk copy
*/
fileContent?: string;
}
@ -751,7 +751,7 @@ declare namespace ts.server.protocol {
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
/**
/**
* A string that is used for comparing completion items so that they can be ordered. This
* is often the same as the name but may be different in certain circumstances.
*/
@ -794,7 +794,7 @@ declare namespace ts.server.protocol {
}
/**
* Signature help information for a single parameter
* Signature help information for a single parameter
*/
export interface SignatureHelpParameter {
@ -814,18 +814,18 @@ declare namespace ts.server.protocol {
displayParts: SymbolDisplayPart[];
/**
* Whether the parameter is optional or not.
* Whether the parameter is optional or not.
*/
isOptional: boolean;
}
/**
* Represents a single signature to show in signature help.
* Represents a single signature to show in signature help.
*/
export interface SignatureHelpItem {
/**
* Whether the signature accepts a variable number of arguments.
* Whether the signature accepts a variable number of arguments.
*/
isVariadic: boolean;
@ -845,7 +845,7 @@ declare namespace ts.server.protocol {
separatorDisplayParts: SymbolDisplayPart[];
/**
* The signature helps items for the parameters.
* The signature helps items for the parameters.
*/
parameters: SignatureHelpParameter[];
@ -861,17 +861,17 @@ declare namespace ts.server.protocol {
export interface SignatureHelpItems {
/**
* The signature help items.
* The signature help items.
*/
items: SignatureHelpItem[];
/**
* The span for which signature help should appear on a signature
* The span for which signature help should appear on a signature
*/
applicableSpan: TextSpan;
/**
* The item selected in the set of available help items.
* The item selected in the set of available help items.
*/
selectedItemIndex: number;
@ -895,7 +895,7 @@ declare namespace ts.server.protocol {
/**
* Signature help request; value of command field is "signatureHelp".
* Given a file location (file, line, col), return the signature
* Given a file location (file, line, col), return the signature
* help.
*/
export interface SignatureHelpRequest extends FileLocationRequest {
@ -926,8 +926,8 @@ declare namespace ts.server.protocol {
}
/**
* GeterrForProjectRequest request; value of command field is
* "geterrForProject". It works similarly with 'Geterr', only
* GeterrForProjectRequest request; value of command field is
* "geterrForProject". It works similarly with 'Geterr', only
* it request for every file in this project.
*/
export interface GeterrForProjectRequest extends Request {
@ -997,7 +997,7 @@ declare namespace ts.server.protocol {
diagnostics: Diagnostic[];
}
/**
/**
* Event message for "syntaxDiag" and "semanticDiag" event types.
* These events provide syntactic and semantic errors for a file.
*/
@ -1033,7 +1033,7 @@ declare namespace ts.server.protocol {
export interface ReloadResponse extends Response {
}
/**
/**
* Arguments for saveto request.
*/
export interface SavetoRequestArgs extends FileRequestArgs {
@ -1109,7 +1109,7 @@ declare namespace ts.server.protocol {
*/
kindModifiers?: string;
/**
/**
* The file in which the symbol is found.
*/
file: string;
@ -1156,7 +1156,7 @@ declare namespace ts.server.protocol {
/**
* Change request message; value of command field is "change".
* Update the server's view of the file named by argument 'file'.
* Update the server's view of the file named by argument 'file'.
* Server does not currently send a response to a change request.
*/
export interface ChangeRequest extends FileLocationRequest {