diff --git a/lib/rules/arrow-body-style.js b/lib/rules/arrow-body-style.js index 8d3b400037a..9d5c77d8573 100644 --- a/lib/rules/arrow-body-style.js +++ b/lib/rules/arrow-body-style.js @@ -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; @@ -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; diff --git a/tests/lib/rules/arrow-body-style.js b/tests/lib/rules/arrow-body-style.js index 4e755c2cab6..7c1bea64ef8 100644 --- a/tests/lib/rules/arrow-body-style.js +++ b/tests/lib/rules/arrow-body-style.js @@ -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};", @@ -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;", @@ -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" }] } ] });