Preserve newlines on either side of a binary expression.

This commit is contained in:
Cyrus Najmabadi 2015-03-07 12:54:12 -08:00
parent 62d304b069
commit 680e48f507
14 changed files with 83 additions and 55 deletions

View File

@ -3290,26 +3290,46 @@ module ts {
else {
emit(node.left);
if (node.operatorToken.kind !== SyntaxKind.CommaToken) {
write(" ");
// If there was a newline between the left side of the binary expression and the
// operator, then try to preserve that.
var indented = false;
var isSynthesied = nodeIsSynthesized(node);
if (!isSynthesied && !nodeEndIsOnSameLineAsNodeStart(node.left, node.operatorToken)) {
indented = true;
increaseIndent();
writeLine();
}
else {
// Otherwise just emit the operator right afterwards. For everything but
// comma, emit a space before the operator.
if (node.operatorToken.kind !== SyntaxKind.CommaToken) {
write(" ");
}
}
write(tokenToString(node.operatorToken.kind));
var shouldPlaceOnNewLine = !nodeIsSynthesized(node) && !nodeEndIsOnSameLineAsNodeStart(node.operatorToken, node.right);
// If there was a newline after the operator (or this is a synthesized node that
// wants to be on a new line), then put a newline in. But only if we haven't
// already done this for the left side.
var wantsIndent = (!isSynthesied && !nodeEndIsOnSameLineAsNodeStart(node.operatorToken, node.right)) ||
synthesizedNodeStartsOnNewLine(node.right);
// Check if the right expression is on a different line versus the operator itself. If so,
// we'll emit newline.
if (shouldPlaceOnNewLine || synthesizedNodeStartsOnNewLine(node.right)) {
if (wantsIndent && !indented) {
indented = true;
increaseIndent();
writeLine();
emit(node.right);
decreaseIndent();
}
else {
write(" ");
emit(node.right);
}
// If we indented the left or the right side, then dedent now.
if (indented) {
decreaseIndent();
}
}
}

View File

@ -2052,7 +2052,8 @@ function transform(contents, compilerOptions) {
return {
outputs: outputs,
errors: errors.map(function (e) {
return e.file.fileName + "(" + (e.file.getLineAndCharacterOfPosition(e.start).line + 1) + "): " + ts.flattenDiagnosticMessageText(e.messageText, os.EOL);
return e.file.fileName + "(" + (e.file.getLineAndCharacterOfPosition(e.start).line + 1) + "): "
+ ts.flattenDiagnosticMessageText(e.messageText, os.EOL);
})
};
}

View File

@ -37,9 +37,9 @@ y
//// [asiArith.js]
var x = 1;
var y = 1;
var z = x +
+ +y;
var z = x
+ + +y;
var a = 1;
var b = 1;
var c = x -
- -y;
var c = x
- - -y;

View File

@ -314,8 +314,7 @@ var TypeScriptAllInOne;
Program.prototype.if = function (retValue) {
if (retValue === void 0) { retValue = != 0; }
return 1;
^
retValue;
^ retValue;
bfs.TYPES();
if (retValue != 0) {
return 1 &&

View File

@ -5,5 +5,5 @@
2;
//// [parserGreaterThanTokenAmbiguity10.js]
1 >>>
2;
1
>>> 2;

View File

@ -5,5 +5,5 @@
2;
//// [parserGreaterThanTokenAmbiguity15.js]
1 >>=
2;
1
>>= 2;

View File

@ -5,5 +5,5 @@
2;
//// [parserGreaterThanTokenAmbiguity20.js]
1 >>>=
2;
1
>>>= 2;

View File

@ -4,4 +4,4 @@
//// [parserGreaterThanTokenAmbiguity4.js]
1 >
> 2;
> 2;

View File

@ -5,5 +5,5 @@
2;
//// [parserGreaterThanTokenAmbiguity5.js]
1 >>
2;
1
>> 2;

View File

@ -4,4 +4,4 @@
//// [parserGreaterThanTokenAmbiguity9.js]
1 >>
> 2;
> 2;

View File

@ -3,4 +3,5 @@
/notregexp/a.foo();
//// [parserRegularExpressionDivideAmbiguity1.js]
1 / notregexp / a.foo();
1
/ notregexp / a.foo();

View File

@ -157,7 +157,8 @@ function foo10(x) {
var b;
return typeof x === "string" ? x // string
: ((b = x) // x is number | boolean
&& typeof x === "number" && x.toString()); // x is number
&& typeof x === "number"
&& x.toString()); // x is number
}
function foo11(x) {
// Mixing typeguards
@ -165,8 +166,9 @@ function foo11(x) {
var b;
return typeof x === "string" ? x // number | boolean | string - changed in the false branch
: ((b = x) // x is number | boolean | string - because the assignment changed it
&& typeof x === "number" && (x = 10) // assignment to x
&& x); // x is number | boolean | string
&& typeof x === "number"
&& (x = 10) // assignment to x
&& x); // x is number | boolean | string
}
function foo12(x) {
// Mixing typeguards
@ -174,5 +176,6 @@ function foo12(x) {
var b;
return typeof x === "string" ? (x = 10 && x.toString().length) // number | boolean | string - changed here
: ((b = x) // x is number | boolean | string - changed in true branch
&& typeof x === "number" && x); // x is number
&& typeof x === "number"
&& x); // x is number
}

View File

@ -72,36 +72,38 @@ function foo3(x) {
}
function foo4(x) {
return typeof x !== "string" // string | number | boolean
&& typeof x !== "number" // number | boolean
&& x; // boolean
&& typeof x !== "number" // number | boolean
&& x; // boolean
}
function foo5(x) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b;
return typeof x !== "string" // string | number | boolean
&& ((b = x) && (typeof x !== "number" // number | boolean
&& x)); // boolean
&& ((b = x) && (typeof x !== "number" // number | boolean
&& x)); // boolean
}
function foo6(x) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" // string | number | boolean
&& (typeof x !== "number" // number | boolean
? x // boolean
: x === 10); // number
&& (typeof x !== "number" // number | boolean
? x // boolean
: x === 10); // number
}
function foo7(x) {
var y;
var z;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x !== "string" && ((z = x) // string | number | boolean - x changed deeper in conditional expression
&& (typeof x === "number" ? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
return typeof x !== "string"
&& ((z = x) // string | number | boolean - x changed deeper in conditional expression
&& (typeof x === "number" ? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
}
function foo8(x) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x !== "string" && (x = 10) // change x - number| string
&& (typeof x === "number" ? x // number
: x.length); // string
return typeof x !== "string"
&& (x = 10) // change x - number| string
&& (typeof x === "number" ? x // number
: x.length); // string
}

View File

@ -72,36 +72,38 @@ function foo3(x) {
}
function foo4(x) {
return typeof x === "string" // string | number | boolean
|| typeof x === "number" // number | boolean
|| x; // boolean
|| typeof x === "number" // number | boolean
|| x; // boolean
}
function foo5(x) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b;
return typeof x === "string" // string | number | boolean
|| ((b = x) || (typeof x === "number" // number | boolean
|| x)); // boolean
|| ((b = x) || (typeof x === "number" // number | boolean
|| x)); // boolean
}
function foo6(x) {
// Mixing typeguard
return typeof x === "string" // string | number | boolean
|| (typeof x !== "number" // number | boolean
? x // boolean
: x === 10); // number
|| (typeof x !== "number" // number | boolean
? x // boolean
: x === 10); // number
}
function foo7(x) {
var y;
var z;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x === "string" || ((z = x) // string | number | boolean - x changed deeper in conditional expression
|| (typeof x === "number" ? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
return typeof x === "string"
|| ((z = x) // string | number | boolean - x changed deeper in conditional expression
|| (typeof x === "number" ? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
}
function foo8(x) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x === "string" || (x = 10) // change x - number| string
|| (typeof x === "number" ? x // number
: x.length); // string
return typeof x === "string"
|| (x = 10) // change x - number| string
|| (typeof x === "number" ? x // number
: x.length); // string
}