Skip to content

Commit

Permalink
Fix: arrow-body-style crash with object literal body (fixes #12884) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mdjermanovic committed Feb 28, 2020
1 parent afa9aac commit 4797fb2
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 15 deletions.
41 changes: 26 additions & 15 deletions lib/rules/arrow-body-style.js
Expand Up @@ -91,7 +91,7 @@ module.exports = {
* @returns {Token} The found closing parenthesis token.
*/
function findClosingParen(token) {
let node = sourceCode.getNodeByRangeIndex(token.range[1]);
let node = sourceCode.getNodeByRangeIndex(token.range[0]);

while (!astUtils.isParenthesised(sourceCode, node)) {
node = node.parent;
Expand Down Expand Up @@ -206,24 +206,35 @@ module.exports = {
fix(fixer) {
const fixes = [];
const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken);
const firstBodyToken = sourceCode.getTokenAfter(arrowToken);
const lastBodyToken = sourceCode.getLastToken(node);
const [firstTokenAfterArrow, secondTokenAfterArrow] = sourceCode.getTokensAfter(arrowToken, { count: 2 });
const lastToken = sourceCode.getLastToken(node);
const isParenthesisedObjectLiteral =
astUtils.isOpeningParenToken(firstBodyToken) &&
astUtils.isOpeningBraceToken(sourceCode.getTokenAfter(firstBodyToken));

// Wrap the value by a block and a return statement.
fixes.push(
fixer.insertTextBefore(firstBodyToken, "{return "),
fixer.insertTextAfter(lastBodyToken, "}")
);
astUtils.isOpeningParenToken(firstTokenAfterArrow) &&
astUtils.isOpeningBraceToken(secondTokenAfterArrow);

// If the value is object literal, remove parentheses which were forced by syntax.
if (isParenthesisedObjectLiteral) {
fixes.push(
fixer.remove(firstBodyToken),
fixer.remove(findClosingParen(firstBodyToken))
);
const openingParenToken = firstTokenAfterArrow;
const openingBraceToken = secondTokenAfterArrow;

if (astUtils.isTokenOnSameLine(openingParenToken, openingBraceToken)) {
fixes.push(fixer.replaceText(openingParenToken, "{return "));
} else {

// Avoid ASI
fixes.push(
fixer.replaceText(openingParenToken, "{"),
fixer.insertTextBefore(openingBraceToken, "return ")
);
}

// Closing paren for the object doesn't have to be lastToken, e.g.: () => ({}).foo()
fixes.push(fixer.remove(findClosingParen(openingBraceToken)));
fixes.push(fixer.insertTextAfter(lastToken, "}"));

} else {
fixes.push(fixer.insertTextBefore(firstTokenAfterArrow, "{return "));
fixes.push(fixer.insertTextAfter(lastToken, "}"));
}

return fixes;
Expand Down
94 changes: 94 additions & 0 deletions tests/lib/rules/arrow-body-style.js
Expand Up @@ -45,6 +45,19 @@ ruleTester.run("arrow-body-style", rule, {
{ code: "var foo = () => { return { bar: 0 }; };", options: ["as-needed", { requireReturnForObjectLiteral: true }] }
],
invalid: [
{
code: "var foo = () => 0",
output: "var foo = () => {return 0}",
options: ["always"],
errors: [
{
line: 1,
column: 17,
type: "ArrowFunctionExpression",
messageId: "expectedBlock"
}
]
},
{
code: "var foo = () => 0;",
output: "var foo = () => {return 0};",
Expand All @@ -71,6 +84,45 @@ ruleTester.run("arrow-body-style", rule, {
}
]
},
{
code: "var foo = () => ( {});",
output: "var foo = () => {return {}};",
options: ["always"],
errors: [
{
line: 1,
column: 20,
type: "ArrowFunctionExpression",
messageId: "expectedBlock"
}
]
},
{
code: "(() => ({}))",
output: "(() => {return {}})",
options: ["always"],
errors: [
{
line: 1,
column: 9,
type: "ArrowFunctionExpression",
messageId: "expectedBlock"
}
]
},
{
code: "(() => ( {}))",
output: "(() => {return {}})",
options: ["always"],
errors: [
{
line: 1,
column: 10,
type: "ArrowFunctionExpression",
messageId: "expectedBlock"
}
]
},
{
code: "var foo = () => { return 0; };",
output: "var foo = () => 0;",
Expand Down Expand Up @@ -472,6 +524,48 @@ ruleTester.run("arrow-body-style", rule, {
output: "var foo = () => {return {foo: 1}.foo()};",
options: ["always"],
errors: [{ messageId: "expectedBlock" }]
},
{
code: "var foo = () => ( {foo: 1} ).foo();",
output: "var foo = () => {return {foo: 1} .foo()};",
options: ["always"],
errors: [{ messageId: "expectedBlock" }]
},
{
code: `
var foo = () => ({
bar: 1,
baz: 2
});
`,
output: `
var foo = () => {return {
bar: 1,
baz: 2
}};
`,
options: ["always"],
errors: [{ messageId: "expectedBlock" }]
},
{
code: `
parsedYears = _map(years, (year) => (
{
index : year,
title : splitYear(year)
}
));
`,
output: `
parsedYears = _map(years, (year) => {
return {
index : year,
title : splitYear(year)
}
});
`,
options: ["always"],
errors: [{ messageId: "expectedBlock" }]
}
]
});

0 comments on commit 4797fb2

Please sign in to comment.