Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: arrow-body-style fixer for in wrap (fixes #11849) #13228

Merged
merged 12 commits into from Jul 11, 2020
22 changes: 21 additions & 1 deletion lib/rules/arrow-body-style.js
Expand Up @@ -99,6 +99,24 @@ module.exports = {
return sourceCode.getTokenAfter(node);
}

/**
* check if node has `in` operator or not
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
* @param {Node} node The argument node which needs to be checked
* @returns {boolean} `true` if there is an `in` operator else `false`.
*/
function isIn(node) {
if (
node.type === "BinaryExpression" ||
node.type === "LogicalExpression"
mdjermanovic marked this conversation as resolved.
Show resolved Hide resolved
) {
if (node.operator === "in") {
return true;
}
return isIn(node.left) || isIn(node.right);
}
return false;
}

/**
* Determines whether a arrow function body needs braces
* @param {ASTNode} node The arrow function node.
Expand Down Expand Up @@ -157,6 +175,8 @@ module.exports = {
sourceCode.commentsExistBetween(openingBrace, firstValueToken) ||
sourceCode.commentsExistBetween(lastValueToken, closingBrace);

const isInOp = isIn(blockBody[0].argument);

/*
* Remove tokens around the return value.
* If comments don't exist, remove extra spaces as well.
Expand All @@ -178,7 +198,7 @@ module.exports = {
* If the first token of the reutrn value is `{` or the return value is a sequence expression,
* enclose the return value by parentheses to avoid syntax error.
*/
if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression") {
if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression" || isInOp) {
fixes.push(
fixer.insertTextBefore(firstValueToken, "("),
fixer.insertTextAfter(lastValueToken, ")")
Expand Down
71 changes: 71 additions & 0 deletions tests/lib/rules/arrow-body-style.js
Expand Up @@ -45,6 +45,77 @@ ruleTester.run("arrow-body-style", rule, {
{ code: "var foo = () => { return { bar: 0 }; };", options: ["as-needed", { requireReturnForObjectLiteral: true }] }
],
invalid: [
{
code: "for (let a = (b, c, d) => { return vb && c in d; }; ;);",
output: "for (let a = (b, c, d) => (vb && c in d); ;);",
errors: [
{
line: 1,
column: 27,
messageId: "unexpectedSingleBlock"
}
]
},
{
code: "for (let a = (b, c, d) => { return v in b && c in d; }; ;);",
output: "for (let a = (b, c, d) => (v in b && c in d); ;);",
errors: [
{
line: 1,
column: 27,
messageId: "unexpectedSingleBlock"
}
]
},
{
code: "for (let a = (b, c, d) => { return vb in dd ; }; ;);",
output: "for (let a = (b, c, d) => (vb in dd ); ;);",
errors: [
{
line: 1,
column: 27,
messageId: "unexpectedSingleBlock"
}
]
},
{
code: "for (let a = (b, c, d) => { return vb in c in dd ; }; ;);",
output: "for (let a = (b, c, d) => (vb in c in dd ); ;);",
errors: [
{
line: 1,
column: 27,
messageId: "unexpectedSingleBlock"
}
]
},
{
code: "do{let a = () => {return f in ff}}while(true){}",
output: "do{let a = () => (f in ff)}while(true){}",
errors: [{
line: 1,
column: 18,
messageId: "unexpectedSingleBlock"
}]
},
{
code: "scores.map(score => { return x in +(score / maxScore).toFixed(2)});",
output: "scores.map(score => (x in +(score / maxScore).toFixed(2)));",
errors: [{
line: 1,
column: 21,
messageId: "unexpectedSingleBlock"
}]
},
{
code: "const fn = (a, b) => { return a + x in Number(b) };",
output: "const fn = (a, b) => (a + x in Number(b));",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
errors: [{
line: 1,
column: 22,
messageId: "unexpectedSingleBlock"
}]
},
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
{
code: "var foo = () => 0",
output: "var foo = () => {return 0}",
Expand Down