Keep parens around do-expressions inside ExpressionStatement (#4479)
This commit is contained in:
1 parent
983202413c
commit
857c55bd61
5 files changed
+177
-16
No files matched your search
+24
-13
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 "{}";
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
`;
|
||||
@@ -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];
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user