Fixes emit for module/enum and single-line arrow functions.

This commit is contained in:
Ron Buckton 2016-03-21 15:50:52 -07:00
parent 9bbbb33df5
commit 25998ae865
6 changed files with 125 additions and 68 deletions

View file

@ -452,11 +452,15 @@ namespace ts {
return node;
}
export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange) {
export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange, options?: { startOnNewLine?: boolean; }) {
const node = <IfStatement>createNode(SyntaxKind.IfStatement, location);
node.expression = expression;
node.thenStatement = thenStatement;
node.elseStatement = elseStatement;
if (options && options.startOnNewLine) {
node.startsOnNewLine = true;
}
return node;
}

View file

@ -1411,30 +1411,41 @@ const _super = (function (geti, seti) {
}
function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) {
// We must emit a function body as a single-line body in the following case:
// * The body has NodeEmitFlags.SingleLine specified.
// We must emit a function body as a multi-line body in the following cases:
// * The body is explicitly marked as multi-line.
// * A non-synthesized body's start and end position are on different lines.
// * Any statement in the body starts on a new line.
if (getNodeEmitFlags(body) & NodeEmitFlags.SingleLine) {
return true;
}
if (body.multiLine) {
return false;
}
const originalNode = getOriginalNode(parentNode);
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;
}
}
else {
return rangeEndIsOnSameLineAsRangeStart((<ArrowFunction>originalNode).equalsGreaterThanToken, originalNode.body);
}
if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) {
return false;
}
return false;
if (shouldWriteLeadingLineTerminator(body, body.statements, ListFormat.PreserveLines)
|| shouldWriteClosingLineTerminator(body, body.statements, ListFormat.PreserveLines)) {
return false;
}
let previousStatement: Statement;
for (const statement of body.statements) {
if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) {
return false;
}
previousStatement = statement;
}
return true;
}
function emitBlockFunctionBody(parentNode: Node, body: Block) {
@ -1457,7 +1468,7 @@ const _super = (function (geti, seti) {
const endingLine = writer.getLine();
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
emitLeadingComments(collapseTextRange(body.statements, TextRangeCollapse.CollapseToEnd));
emitLeadingComments(collapseRangeToEnd(body.statements));
decreaseIndent();
}
@ -1738,7 +1749,7 @@ const _super = (function (geti, seti) {
}
function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray<Statement>) {
if (statements.length === 1 && rangeStartPositionsAreOnSameLine(parentNode, statements[0])) {
if (statements.length === 1 && rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)) {
write(" ");
emit(statements[0]);
}
@ -1778,7 +1789,7 @@ const _super = (function (geti, seti) {
// }
// "comment1" is not considered to be leading comment for node.initializer
// but rather a trailing comment on the previous node.
emitLeadingComments(node.initializer, getTrailingComments(collapseTextRange(node.initializer, TextRangeCollapse.CollapseToStart)));
emitLeadingComments(node.initializer, getTrailingComments(collapseRangeToStart(node.initializer)));
emitExpression(node.initializer);
}
@ -2236,13 +2247,13 @@ const _super = (function (geti, seti) {
const firstChild = children[0];
if (firstChild === undefined) {
return !positionsAreOnSameLine(getStartPos(parentNode), parentNode.end);
return !rangeIsOnSingleLine(parentNode, currentSourceFile);
}
else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) {
return synthesizedNodeStartsOnNewLine(firstChild, format);
}
else {
return !rangeStartPositionsAreOnSameLine(parentNode, firstChild);
return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile);
}
}
else {
@ -2262,7 +2273,7 @@ const _super = (function (geti, seti) {
return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format);
}
else {
return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode);
return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile);
}
}
else {
@ -2281,13 +2292,13 @@ const _super = (function (geti, seti) {
const lastChild = lastOrUndefined(children);
if (lastChild === undefined) {
return !positionsAreOnSameLine(getStartPos(parentNode), parentNode.end);
return !rangeIsOnSingleLine(parentNode, currentSourceFile);
}
else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) {
return synthesizedNodeStartsOnNewLine(lastChild, format);
}
else {
return !rangeEndPositionsAreOnSameLine(parentNode, lastChild);
return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile);
}
}
else {
@ -2304,30 +2315,10 @@ const _super = (function (geti, seti) {
return startsOnNewLine;
}
return (format & ListFormat.PreferNewLine) !== 0;
}
function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange) {
return positionsAreOnSameLine(getStartPos(range1), getStartPos(range2));
}
function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange) {
return positionsAreOnSameLine(range1.end, range2.end);
}
function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange) {
return positionsAreOnSameLine(range1.end, getStartPos(range2));
}
function positionsAreOnSameLine(pos1: number, pos2: number) {
return pos1 === pos2 ||
getLineOfLocalPosition(currentSourceFile, pos1) === getLineOfLocalPosition(currentSourceFile, pos2);
}
function getStartPos(range: TextRange) {
return range.pos === -1 ? -1 : skipTrivia(currentText, range.pos);
}
function needsIndentation(parent: Node, node1: Node, node2: Node): boolean {
parent = skipSynthesizedParentheses(parent);
node1 = skipSynthesizedParentheses(node1);
@ -2341,7 +2332,7 @@ const _super = (function (geti, seti) {
return !nodeIsSynthesized(parent)
&& !nodeIsSynthesized(node1)
&& !nodeIsSynthesized(node2)
&& !rangeEndIsOnSameLineAsRangeStart(node1, node2);
&& !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile);
}
function skipSynthesizedParentheses(node: Node) {
@ -2381,7 +2372,7 @@ const _super = (function (geti, seti) {
function isSingleLineEmptyBlock(block: Block) {
return !block.multiLine
&& block.statements.length === 0
&& rangeEndIsOnSameLineAsRangeStart(block, block);
&& rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile);
}
function getNotEmittedParent(node: Node): Node {

View file

@ -994,8 +994,8 @@ namespace ts {
const start = new Date().getTime();
// TODO(rbuckton): remove USE_TRANSFORMS condition when we switch to transforms permenantly.
if (Boolean(sys.getEnvironmentVariable("USE_TRANSFORMS"))) {
// TODO(rbuckton): remove USE_TRANSFORMS condition when we switch to transforms permanently.
if (/^(y(es)?|t(rue|ransforms?)?|1|\+)$/i.test(sys.getEnvironmentVariable("USE_TRANSFORMS"))) {
options.experimentalTransforms = true;
}

View file

@ -564,7 +564,10 @@ namespace ts {
)
]),
NodeEmitFlags.SingleLine
)
),
/*elseStatement*/ undefined,
/*location*/ undefined,
{ startOnNewLine: true }
)
);
}
@ -841,25 +844,62 @@ namespace ts {
* @param node A function-like node.
*/
function transformFunctionBody(node: FunctionLikeDeclaration) {
let multiLine = false; // indicates whether the block *must* be emitted as multiple lines
let singleLine = false; // indicates whether the block *may* be emitted as a single line
const statements: Statement[] = [];
startLexicalEnvironment();
addCaptureThisForNodeIfNeeded(statements, node);
addDefaultValueAssignmentsIfNeeded(statements, node);
addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false);
// If we added any generated statements, this must be a multi-line block.
if (!multiLine && statements.length > 0) {
multiLine = true;
}
const body = node.body;
if (isBlock(body)) {
addRange(statements, visitNodes(body.statements, visitor, isStatement));
// If the original body was a multi-line block, this must be a multi-line block.
if (!multiLine && body.multiLine) {
multiLine = true;
}
}
else {
Debug.assert(node.kind === SyntaxKind.ArrowFunction);
const equalsGreaterThanToken = (<ArrowFunction>node).equalsGreaterThanToken;
if (!nodeIsSynthesized(equalsGreaterThanToken) && !nodeIsSynthesized(body)) {
if (rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) {
singleLine = true;
}
else {
multiLine = true;
}
}
const expression = visitNode(body, visitor, isExpression);
if (expression) {
statements.push(createReturn(expression, /*location*/ body));
statements.push(createReturn(expression));
}
}
addRange(statements, endLexicalEnvironment());
return createBlock(statements, node.body);
const lexicalEnvironment = endLexicalEnvironment();
addRange(statements, lexicalEnvironment);
// If we added any final generated statements, this must be a multi-line block
if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) {
multiLine = true;
}
const block = createBlock(statements, node.body, multiLine);
if (!multiLine && singleLine) {
setNodeEmitFlags(block, NodeEmitFlags.SingleLine);
}
return block;
}
/**

View file

@ -2228,7 +2228,7 @@ namespace ts {
startLexicalEnvironment();
addNodes(statements, map(node.members, transformEnumMember));
addNodes(statements, endLexicalEnvironment());
return createBlock(statements);
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
}
/**
@ -2455,7 +2455,7 @@ namespace ts {
}
addNodes(statements, endLexicalEnvironment());
return createBlock(statements);
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
}
/**

View file

@ -2925,19 +2925,41 @@ namespace ts {
}
}
export const enum TextRangeCollapse {
CollapseToStart,
CollapseToEnd,
export function collapseRangeToStart(range: TextRange) {
return range.pos === range.end ? range : { pos: range.pos, end: range.pos };
}
export function collapseTextRange(range: TextRange, collapse: TextRangeCollapse) {
if (range.pos === range.end) {
return range;
}
export function collapseRangeToEnd(range: TextRange) {
return range.pos === range.end ? range : { pos: range.end, end: range.end };
}
return collapse === TextRangeCollapse.CollapseToStart
? { pos: range.pos, end: range.pos }
: { pos: range.end, end: range.end };
export function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile) {
return rangeStartIsOnSameLineAsRangeEnd(range, range, sourceFile);
}
export function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), getStartPositionOfRange(range2, sourceFile), sourceFile);
}
export function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
return positionsAreOnSameLine(range1.end, range2.end, sourceFile);
}
export function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), range2.end, sourceFile);
}
export function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile), sourceFile);
}
export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile) {
return pos1 === pos2 ||
getLineOfLocalPosition(sourceFile, pos1) === getLineOfLocalPosition(sourceFile, pos2);
}
export function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile) {
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos);
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver) {