Keep parens around do-expressions inside ExpressionStatement (#4479)

This commit is contained in:
Brian Ng authored and GitHub committed 2018-05-15 11:41:17 -05:00
1 parent 983202413c
commit 857c55bd61
5 files changed
+177 -16

No files matched your search

+24 -13
View File
@@ -369,54 +369,65 @@ function isBitwiseOperator(operator) {
);
}
// Tests if an expression starts with `{`, or (if forbidFunctionAndClass holds) `function` or `class`.
// Will be overzealous if there's already necessary grouping parentheses.
function startsWithNoLookaheadToken(node, forbidFunctionAndClass) {
// Tests if an expression starts with `{`, or (if forbidFunctionClassAndDoExpr
// holds) `function`, `class`, or `do {}`. Will be overzealous if there's
// already necessary grouping parentheses.
function startsWithNoLookaheadToken(node, forbidFunctionClassAndDoExpr) {
node = getLeftMost(node);
switch (node.type) {
// Hack. Remove after https://github.com/eslint/typescript-eslint-parser/issues/331
case "ObjectPattern":
return !forbidFunctionAndClass;
return !forbidFunctionClassAndDoExpr;
case "FunctionExpression":
case "ClassExpression":
return forbidFunctionAndClass;
case "DoExpression":
return forbidFunctionClassAndDoExpr;
case "ObjectExpression":
return true;
case "MemberExpression":
return startsWithNoLookaheadToken(node.object, forbidFunctionAndClass);
return startsWithNoLookaheadToken(
node.object,
forbidFunctionClassAndDoExpr
);
case "TaggedTemplateExpression":
if (node.tag.type === "FunctionExpression") {
// IIFEs are always already parenthesized
return false;
}
return startsWithNoLookaheadToken(node.tag, forbidFunctionAndClass);
return startsWithNoLookaheadToken(node.tag, forbidFunctionClassAndDoExpr);
case "CallExpression":
if (node.callee.type === "FunctionExpression") {
// IIFEs are always already parenthesized
return false;
}
return startsWithNoLookaheadToken(node.callee, forbidFunctionAndClass);
return startsWithNoLookaheadToken(
node.callee,
forbidFunctionClassAndDoExpr
);
case "ConditionalExpression":
return startsWithNoLookaheadToken(node.test, forbidFunctionAndClass);
return startsWithNoLookaheadToken(
node.test,
forbidFunctionClassAndDoExpr
);
case "UpdateExpression":
return (
!node.prefix &&
startsWithNoLookaheadToken(node.argument, forbidFunctionAndClass)
startsWithNoLookaheadToken(node.argument, forbidFunctionClassAndDoExpr)
);
case "BindExpression":
return (
node.object &&
startsWithNoLookaheadToken(node.object, forbidFunctionAndClass)
startsWithNoLookaheadToken(node.object, forbidFunctionClassAndDoExpr)
);
case "SequenceExpression":
return startsWithNoLookaheadToken(
node.expressions[0],
forbidFunctionAndClass
forbidFunctionClassAndDoExpr
);
case "TSAsExpression":
return startsWithNoLookaheadToken(
node.expression,
forbidFunctionAndClass
forbidFunctionClassAndDoExpr
);
default:
return false;
+5 -2
View File
@@ -91,10 +91,13 @@ function needsParens(path, options) {
node.type !== "SequenceExpression" && // these have parens added anyway
util.startsWithNoLookaheadToken(
node,
/* forbidFunctionAndClass */ false
/* forbidFunctionClassAndDoExpr */ false
)) ||
(parent.type === "ExpressionStatement" &&
util.startsWithNoLookaheadToken(node, /* forbidFunctionAndClass */ true))
util.startsWithNoLookaheadToken(
node,
/* forbidFunctionClassAndDoExpr */ true
))
) {
return true;
}
+3 -1
View File
@@ -661,7 +661,8 @@ function printPathNoParens(path, options, print, args) {
n.body.type === "BlockStatement" ||
isJSXNode(n.body) ||
isTemplateOnItsOwnLine(n.body, options.originalText, options) ||
n.body.type === "ArrowFunctionExpression")
n.body.type === "ArrowFunctionExpression" ||
n.body.type === "DoExpression")
) {
return group(concat([concat(parts), " ", body]));
}
@@ -912,6 +913,7 @@ function printPathNoParens(path, options, print, args) {
parent.type === "ForStatement" ||
parent.type === "WhileStatement" ||
parent.type === "DoWhileStatement" ||
parent.type === "DoExpression" ||
(parent.type === "CatchClause" && !parentParent.finalizer))
) {
return "{}";
+98
View File
@@ -8,6 +8,53 @@ const envSpecific = {
else if(env === 'development') 'http://localhost:4000';
}
};
let x = do {
let tmp = f();
tmp * tmp + 1
};
let x = do {
if (foo()) { f() }
else if (bar()) { g() }
else { h() }
};
function foo() {
return (
<nav>
<Home />
{
do {
if (loggedIn) {
<LogoutButton />
} else {
<LoginButton />
}
}
}
</nav>
);
}
(do {});
(do {} + 1);
(1 + do {});
() => do {};
(do {
switch(0) {
case 0: "foo";
case 1: break;
}
});
() => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const envSpecific = {
domain: do {
@@ -16,4 +63,55 @@ const envSpecific = {
}
};
let x = do {
let tmp = f();
tmp * tmp + 1;
};
let x = do {
if (foo()) {
f();
} else if (bar()) {
g();
} else {
h();
}
};
function foo() {
return (
<nav>
<Home />
{do {
if (loggedIn) {
<LogoutButton />;
} else {
<LoginButton />;
}
}}
</nav>
);
}
(do {});
(do {} + 1);
1 + do {};
() => do {};
(do {
switch (0) {
case 0:
"foo";
case 1:
break;
}
});
() => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
`;
+47
View File
@@ -5,3 +5,50 @@ const envSpecific = {
else if(env === 'development') 'http://localhost:4000';
}
};
let x = do {
let tmp = f();
tmp * tmp + 1
};
let x = do {
if (foo()) { f() }
else if (bar()) { g() }
else { h() }
};
function foo() {
return (
<nav>
<Home />
{
do {
if (loggedIn) {
<LogoutButton />
} else {
<LoginButton />
}
}
}
</nav>
);
}
(do {});
(do {} + 1);
(1 + do {});
() => do {};
(do {
switch(0) {
case 0: "foo";
case 1: break;
}
});
() => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};