Merged some changes from other branches.

This commit is contained in:
Ron Buckton
2016-02-22 16:10:32 -08:00
parent 90a317f62e
commit 6d273366d3
9 changed files with 436 additions and 223 deletions

View File

@@ -222,6 +222,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);
@@ -281,6 +282,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");
@@ -404,6 +409,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

@@ -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 as `/*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 as `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) {
@@ -182,7 +216,7 @@ namespace ts {
// get the leading comments from detachedPos
const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos;
const leadingComments = getLeadingCommentRanges(currentText, pos);
if (detachedCommentsInfo.length > 1) {
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
}
else {

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

@@ -1915,7 +1915,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (multiLine) {
decreaseIndent();
writeLine();
}
write(")");
@@ -2242,6 +2241,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return node;
}
function skipAssertions(node: Expression): Expression {
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
}
return node;
}
function emitCallTarget(node: Expression): Expression {
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword) {
emit(node);
@@ -3308,8 +3314,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// we can't reuse 'arr' because it might be modified within the body of the loop.
const counter = createTempVariable(TempFlags._i);
const rhsReference = createSynthesizedNode(SyntaxKind.Identifier) as Identifier;
rhsReference.text = node.expression.kind === SyntaxKind.Identifier ?
makeUniqueName((<Identifier>node.expression).text) :
const expressionWithoutAssertions = skipAssertions(node.expression);
rhsReference.text = expressionWithoutAssertions.kind === SyntaxKind.Identifier ?
makeUniqueName((<Identifier>expressionWithoutAssertions).text) :
makeTempVariableName(TempFlags.Auto);
// This is the let keyword for the counter and rhsReference. The let keyword for
@@ -4324,7 +4331,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
writeLine();
emitStart(restParam);
emitNodeWithCommentsAndWithoutSourcemap(restParam.name);
write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
write(restIndex > 0
? `[${tempName} - ${restIndex}] = arguments[${tempName}];`
: `[${tempName}] = arguments[${tempName}];`);
emitEnd(restParam);
decreaseIndent();
writeLine();
@@ -5340,6 +5349,18 @@ const _super = (function (geti, seti) {
write(" = ");
}
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
let tempVariable: Identifier;
if (isClassExpressionWithStaticProperties) {
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
write("(");
increaseIndent();
emit(tempVariable);
write(" = ");
}
write("(function (");
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {
@@ -5369,9 +5390,6 @@ const _super = (function (geti, seti) {
writeLine();
emitConstructor(node, baseTypeNode);
emitMemberFunctionsForES5AndLower(node);
emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true));
writeLine();
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
writeLine();
emitToken(SyntaxKind.CloseBraceToken, node.members.end, () => {
write("return ");
@@ -5398,7 +5416,23 @@ const _super = (function (geti, seti) {
write("))");
if (node.kind === SyntaxKind.ClassDeclaration) {
write(";");
emitPropertyDeclarations(node, staticProperties);
writeLine();
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
}
else if (isClassExpressionWithStaticProperties) {
for (const property of staticProperties) {
write(",");
writeLine();
emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true);
}
write(",");
writeLine();
emit(tempVariable);
decreaseIndent();
write(")");
}
emitEnd(node);
if (node.kind === SyntaxKind.ClassDeclaration) {
@@ -7937,7 +7971,7 @@ const _super = (function (geti, seti) {
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitTrailingComments(node: Node) {
@@ -7949,7 +7983,7 @@ const _super = (function (geti, seti) {
const trailingComments = getTrailingCommentsToEmit(node);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
}
/**
@@ -7964,8 +7998,8 @@ const _super = (function (geti, seti) {
const trailingComments = getTrailingCommentRanges(currentText, pos);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitLeadingCommentsOfPositionWorker(pos: number) {
@@ -7986,7 +8020,7 @@ const _super = (function (geti, seti) {
emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange) {

View File

@@ -75,6 +75,15 @@ function __export(m) {
}
})`;
const superHelper = `
const _super = name => super[name];`;
const advancedSuperHelper = `
const _super = (function (geti, seti) {
const cache = Object.create(null);
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
})(name => super[name], (name, value) => super[name] = value);`;
const compilerOptions = host.getCompilerOptions();
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
@@ -110,20 +119,41 @@ function __export(m) {
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;
let endLexicalEnvironment: () => Statement[];
let getNodeEmitFlags: (node: Node) => NodeEmitFlags;
let isExpressionSubstitutionEnabled: (node: Node) => boolean;
let isEmitNotificationEnabled: (node: Node) => boolean;
let expressionSubstitution: (node: Expression) => Expression;
let identifierSubstitution: (node: Identifier) => Identifier;
let onBeforeEmitNode: (node: Node) => void;
let onAfterEmitNode: (node: Node) => void;
let isUniqueName: (name: string) => boolean;
let temporaryVariables: string[] = [];
let tempFlags: TempFlags;
@@ -177,8 +207,12 @@ function __export(m) {
startLexicalEnvironment = undefined;
endLexicalEnvironment = undefined;
getNodeEmitFlags = undefined;
isExpressionSubstitutionEnabled = undefined;
isEmitNotificationEnabled = undefined;
expressionSubstitution = undefined;
identifierSubstitution = undefined;
onBeforeEmitNode = undefined;
onAfterEmitNode = undefined;
isUniqueName = undefined;
temporaryVariables = undefined;
tempFlags = 0;
@@ -196,8 +230,12 @@ function __export(m) {
startLexicalEnvironment = context.startLexicalEnvironment;
endLexicalEnvironment = context.endLexicalEnvironment;
getNodeEmitFlags = context.getNodeEmitFlags;
isExpressionSubstitutionEnabled = context.isExpressionSubstitutionEnabled;
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
expressionSubstitution = context.expressionSubstitution;
identifierSubstitution = context.identifierSubstitution;
onBeforeEmitNode = context.onBeforeEmitNode;
onAfterEmitNode = context.onAfterEmitNode;
isUniqueName = context.isUniqueName;
return printSourceFile;
}
@@ -212,18 +250,46 @@ function __export(m) {
}
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 leadingComments = getLeadingCommentsToEmit(node);
const trailingComments = getTrailingCommentsToEmit(node);
const adviseOnEmit = isEmitNotificationEnabled(node);
if (adviseOnEmit && onBeforeEmitNode) {
onBeforeEmitNode(node);
}
const leadingComments = getLeadingComments(node, getNotEmittedParent);
const trailingComments = getTrailingComments(node, getNotEmittedParent);
emitLeadingComments(node, leadingComments);
emitStart(node);
emitWorker(node);
emitEnd(node);
emitTrailingComments(node, trailingComments);
if (adviseOnEmit && onAfterEmitNode) {
onAfterEmitNode(node);
}
}
}
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
@@ -234,7 +300,11 @@ function __export(m) {
// Identifiers
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node, identifierSubstitution);
if (tryEmitSubstitute(node, identifierSubstitution)) {
return;
}
return emitIdentifier(<Identifier>node);
// Reserved words
case SyntaxKind.ConstKeyword:
@@ -324,7 +394,7 @@ function __export(m) {
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>node);
case SyntaxKind.ThisType:
return write("this");
return emitThisType(<ThisTypeNode>node);
case SyntaxKind.StringLiteralType:
return emitLiteral(<StringLiteralTypeNode>node);
@@ -340,7 +410,7 @@ function __export(m) {
case SyntaxKind.TemplateSpan:
return emitTemplateSpan(<TemplateSpan>node);
case SyntaxKind.SemicolonClassElement:
return write(";");
return emitSemicolonClassElement(<SemicolonClassElement>node);
// Statements
case SyntaxKind.Block:
@@ -348,7 +418,7 @@ function __export(m) {
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:
@@ -467,25 +537,17 @@ function __export(m) {
// 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)) {
return;
}
switch (kind) {
// Literals
case SyntaxKind.NumericLiteral:
@@ -496,16 +558,15 @@ function __export(m) {
// Identifiers
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node, expressionSubstitution);
return emitIdentifier(<Identifier>node);
// Reserved words
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.TrueKeyword:
return writeTokenNode(node);
case SyntaxKind.ThisKeyword:
return emitThisKeyword(<PrimaryExpression>node);
return writeTokenNode(node);
// Expressions
case SyntaxKind.ArrayLiteralExpression:
@@ -597,17 +658,14 @@ function __export(m) {
// Identifiers
//
function emitIdentifier(node: Identifier, substitution: (node: Node) => Node) {
if (tryEmitSubstitute(node, substitution)) {
return;
}
else if (node.text === undefined) {
function emitIdentifier(node: Identifier) {
if (node.text === undefined) {
// Emit a temporary variable name for this node.
const nodeId = getOriginalNodeId(node);
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);
}
@@ -620,15 +678,6 @@ function __export(m) {
}
}
function emitThisKeyword(node: PrimaryExpression) {
if (tryEmitSubstitute(node, expressionSubstitution)) {
return;
}
else {
writeTokenNode(node);
}
}
//
// Names
//
@@ -716,13 +765,13 @@ function __export(m) {
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) {
@@ -730,7 +779,7 @@ function __export(m) {
emitModifiers(node, node.modifiers);
write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
emit(node.name);
emitSignatureAndBody(node);
emitSignatureAndBody(node, emitSignatureHead);
}
function emitCallSignature(node: CallSignatureDeclaration) {
@@ -760,6 +809,10 @@ function __export(m) {
write(";");
}
function emitSemicolonClassElement(node: SemicolonClassElement) {
write(";");
}
//
// Types
//
@@ -826,6 +879,10 @@ function __export(m) {
write(")");
}
function emitThisType(node: ThisTypeNode) {
write("this");
}
//
// Binding patterns
//
@@ -871,7 +928,7 @@ function __export(m) {
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);
}
}
@@ -882,7 +939,7 @@ function __export(m) {
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);
}
@@ -973,27 +1030,8 @@ function __export(m) {
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) {
@@ -1051,19 +1089,11 @@ function __export(m) {
}
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
if (tryEmitSubstitute(node, expressionSubstitution)) {
return;
}
emitExpression(node.operand);
writeToken(node.operator);
}
function emitBinaryExpression(node: BinaryExpression) {
if (tryEmitSubstitute(node, expressionSubstitution)) {
return;
}
const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken;
const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken);
const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right);
@@ -1169,6 +1199,10 @@ function __export(m) {
write(";");
}
function emitEmptyStatement(node: EmptyStatement) {
write(";");
}
function emitExpressionStatement(node: ExpressionStatement) {
emitExpression(node.expression);
write(";");
@@ -1336,25 +1370,27 @@ function __export(m) {
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);
@@ -1371,34 +1407,49 @@ function __export(m) {
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) {
const startingLine = writer.getLine();
increaseIndent();
emitDetachedComments(body.statements);
// Emit all the prologue directives (like "use strict").
const statements = body.statements;
const statementOffset = emitPrologueDirectives(statements, /*startWithNewLine*/ true, /*indented*/ true);
const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true);
const helpersEmitted = emitHelpers(body);
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) {
@@ -1668,6 +1719,8 @@ function __export(m) {
write("case ");
emitExpression(node.expression);
write(":");
debugger;
emitCaseOrDefaultClauseStatements(node, node.statements);
}
@@ -1688,6 +1741,7 @@ function __export(m) {
function emitHeritageClause(node: HeritageClause) {
emitStart(node);
write(" ");
writeToken(node.token);
write(" ");
emitList(node, node.types, ListFormat.HeritageClauseTypes);
@@ -1783,8 +1837,7 @@ function __export(m) {
}
}
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, indented?: boolean) {
increaseIndentIf(indented);
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean) {
for (let i = 0; i < statements.length; i++) {
if (isPrologueDirective(statements[i])) {
if (startWithNewLine || i > 0) {
@@ -1794,12 +1847,10 @@ function __export(m) {
}
else {
// return index of the first non prologue directive
decreaseIndentIf(indented);
return i;
}
}
decreaseIndentIf(indented);
return statements.length;
}
@@ -1811,7 +1862,17 @@ function __export(m) {
}
if (emitFlags & NodeEmitFlags.EmitExportStar) {
emitExportStarHelper();
writeLines(exportStarHelper);
helpersEmitted = true;
}
if (emitFlags & NodeEmitFlags.EmitSuperHelper) {
writeLines(superHelper);
helpersEmitted = true;
}
if (emitFlags & NodeEmitFlags.EmitAdvancedSuperHelper) {
writeLines(advancedSuperHelper);
helpersEmitted = true;
}
@@ -1861,10 +1922,6 @@ function __export(m) {
return helpersEmitted;
}
function emitExportStarHelper() {
writeLines(exportStarHelper);
}
function writeLines(text: string): void {
const lines = text.split(/\r\n|\r|\n/g);
for (let i = 0; i < lines.length; i++) {
@@ -2027,8 +2084,10 @@ function __export(m) {
}
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(" ");
@@ -2052,12 +2111,20 @@ function __export(m) {
// 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);
@@ -2151,7 +2218,7 @@ function __export(m) {
return true;
}
else if (format & ListFormat.PreserveLines) {
if (getNodeEmitFlags(parentNode) & NodeEmitFlags.MultiLine) {
if (format & ListFormat.PreferNewLine) {
return true;
}
@@ -2193,10 +2260,10 @@ function __export(m) {
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;
}
@@ -2218,7 +2285,7 @@ function __export(m) {
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;
}
@@ -2250,8 +2317,12 @@ function __export(m) {
}
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;
}
@@ -2261,6 +2332,14 @@ function __export(m) {
&& !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;
@@ -2280,9 +2359,9 @@ function __export(m) {
}
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) {
@@ -2383,6 +2462,7 @@ function __export(m) {
// 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,
@@ -2400,7 +2480,7 @@ function __export(m) {
MultiLineBlockStatements = Indented | MultiLine,
VariableDeclarationList = CommaDelimited | SingleLine,
SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenBraces,
MultiLineFunctionBodyStatements = MultiLine | Indented,
MultiLineFunctionBodyStatements = MultiLine,
ClassHeritageClauses = SingleLine,
ClassMembers = Indented | MultiLine,
InterfaceMembers = Indented | MultiLine,
@@ -2409,9 +2489,9 @@ function __export(m) {
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

@@ -7,12 +7,15 @@ namespace ts {
setSourceFile(sourceFile: SourceFile): void;
emitPos(pos: number): void;
emitStart(range: TextRange): void;
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void;
changeEmitSourcePos(): void;
emitEnd(range: TextRange): void;
/*@deprecated*/ emitEnd(range: TextRange, stopOverridingSpan: boolean): void;
/*@deprecated*/ changeEmitSourcePos(): void;
getText(): string;
getSourceMappingURL(): string;
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
reset(): void;
enable(): void;
disable(): void;
}
let nullSourceMapWriter: SourceMapWriter;
@@ -38,6 +41,8 @@ namespace ts {
getSourceMappingURL(): string { return undefined; },
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
reset(): void { },
enable(): void { },
disable(): void { }
};
}
@@ -62,6 +67,8 @@ namespace ts {
// Source map data
let sourceMapData: SourceMapData;
let disableDepth: number;
return {
getSourceMapData: () => sourceMapData,
setSourceFile,
@@ -73,6 +80,8 @@ namespace ts {
getSourceMappingURL,
initialize,
reset,
enable,
disable,
};
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
@@ -81,6 +90,7 @@ namespace ts {
}
currentSourceFile = undefined;
disableDepth = 0;
// Current source map file and its index in the sources list
sourceMapSourceIndex = -1;
@@ -147,6 +157,17 @@ namespace ts {
lastEncodedSourceMapSpan = undefined;
lastEncodedNameIndex = undefined;
sourceMapData = undefined;
disableDepth = 0;
}
function enable() {
if (disableDepth > 0) {
disableDepth--;
}
}
function disable() {
disableDepth++;
}
function updateLastEncodedAndRecordedSpans() {
@@ -168,7 +189,7 @@ namespace ts {
sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] :
defaultLastEncodedSourceMapSpan;
// TODO: Update lastEncodedNameIndex
// TODO: Update lastEncodedNameIndex
// Since we dont support this any more, lets not worry about it right now.
// When we start supporting nameIndex, we will get back to this
@@ -236,7 +257,7 @@ namespace ts {
}
function emitPos(pos: number) {
if (pos === -1) {
if (positionIsSynthesized(pos) || disableDepth > 0) {
return;
}
@@ -288,9 +309,17 @@ namespace ts {
function emitStart(range: TextRange) {
emitPos(getStartPos(range));
if (range.disableSourceMap) {
disable();
}
}
function emitEnd(range: TextRange, stopOverridingEnd?: boolean) {
if (range.disableSourceMap) {
enable();
}
emitPos(range.end);
stopOverridingSpan = stopOverridingEnd;
}

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
@@ -2468,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;
@@ -2793,14 +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.
AdviseOnEmitNode = 1 << 7, // 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` */

View File

@@ -2290,26 +2290,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(" ");
}
}
}
/**
@@ -2366,7 +2373,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 };
}
}
@@ -2705,6 +2712,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 };
}
// Node tests
//
// All node tests in the following list should *not* reference parent pointers so that