From 58cd1e000cc9143231031ba256db5598cd001a6e Mon Sep 17 00:00:00 2001 From: Duncan Beevers Date: Fri, 22 Apr 2016 13:53:11 -0500 Subject: [PATCH] New: `except-object` option for `arrow-body-style` rule. (fixes #5936) Blockless arrow functions are awesome, but when returning an object literal it's necessary to enclose the return value in parentheses. This rule extension enforces blockless arrow functions excluding cases where the arrow function returns an object literal. --- docs/rules/arrow-body-style.md | 24 ++++++++++++++++++++++ lib/rules/arrow-body-style.js | 31 ++++++++++++++++++++++------- tests/lib/rules/arrow-body-style.js | 20 ++++++++++++++++++- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/docs/rules/arrow-body-style.md b/docs/rules/arrow-body-style.md index 8c35d6a7fea..daae3601b4d 100644 --- a/docs/rules/arrow-body-style.md +++ b/docs/rules/arrow-body-style.md @@ -12,6 +12,7 @@ The rule takes one option, a string, which can be: * `"always"` enforces braces around the function body * `"as-needed"` enforces no braces where they can be omitted (default) +* `"except-object"` enforces no braces, except when returning object literals ### "always" @@ -70,3 +71,26 @@ let foo = () => { // do nothing. }; ``` + +### "except-object" + +When the rule is set to `"except-object"` the following patterns are considered problems: + +```js +/*eslint arrow-body-style: ["error", "except-object"]*/ +/*eslit-env es6*/ + +let foo = () => ({ key: 'bar' }); +``` + +The following patterns are not considered problems: + +```js + +/*eslint arrow-body-style: ["error", "except-object"]*/ +/*eslit-env es6*/ + +let foo = () => { + return { key: 'bar' }; +}; +``` diff --git a/lib/rules/arrow-body-style.js b/lib/rules/arrow-body-style.js index 79fde90f805..bc25a48a1b2 100644 --- a/lib/rules/arrow-body-style.js +++ b/lib/rules/arrow-body-style.js @@ -18,7 +18,7 @@ module.exports = { schema: [ { - enum: ["always", "as-needed"] + enum: ["always", "as-needed", "except-object"] } ] }, @@ -26,6 +26,7 @@ module.exports = { create: function(context) { var always = context.options[0] === "always"; var asNeeded = !context.options[0] || context.options[0] === "as-needed"; + var exceptObject = context.options[0] === "except-object"; /** * Determines whether a arrow function body needs braces @@ -42,12 +43,22 @@ module.exports = { return; } - if (asNeeded && blockBody[0].type === "ReturnStatement") { - context.report({ - node: node, - loc: arrowBody.loc.start, - message: "Unexpected block statement surrounding arrow body." - }); + if (blockBody[0].type === "ReturnStatement") { + if (blockBody[0].argument.type !== "ObjectExpression") { + if (exceptObject || asNeeded) { + context.report({ + node: node, + loc: arrowBody.loc.start, + message: "Unexpected block statement surrounding arrow body." + }); + } else if (exceptObject) { + context.report({ + node: node, + loc: arrowBody.loc.start, + message: "Expected block statement surrounding arrow body returning object literal." + }); + } + } } } else { if (always) { @@ -56,6 +67,12 @@ module.exports = { loc: arrowBody.loc.start, message: "Expected block statement surrounding arrow body." }); + } else if (exceptObject && node.body.type === "ObjectExpression") { + context.report({ + node: node, + loc: arrowBody.loc.start, + message: "Unexpected object literal returned from blockless arrow body." + }); } } } diff --git a/tests/lib/rules/arrow-body-style.js b/tests/lib/rules/arrow-body-style.js index fc19dfe081c..489ba969219 100644 --- a/tests/lib/rules/arrow-body-style.js +++ b/tests/lib/rules/arrow-body-style.js @@ -30,7 +30,9 @@ ruleTester.run("arrow-body-style", rule, { { code: "var foo = () => { b = a };", parserOptions: { ecmaVersion: 6 } }, { code: "var foo = () => { bar: 1 };", parserOptions: { ecmaVersion: 6 } }, { code: "var foo = () => { return 0; };", parserOptions: { ecmaVersion: 6 }, options: ["always"] }, - { code: "var foo = () => { return bar(); };", parserOptions: { ecmaVersion: 6 }, options: ["always"] } + { code: "var foo = () => { return bar(); };", parserOptions: { ecmaVersion: 6 }, options: ["always"] }, + { code: "var foo = () => { return { bar: 1 }; };", parserOptions: { ecmaVersion: 6 }, options: ["except-object"] }, + { code: "var foo = () => 0;", parserOptions: { ecmaVersion: 6 }, options: ["except-object"] } ], invalid: [ { @@ -64,6 +66,22 @@ ruleTester.run("arrow-body-style", rule, { errors: [ { line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." } ] + }, + { + code: "var foo = () => ({ bar: 1 });", + parserOptions: { ecmaVersion: 6 }, + options: ["except-object"], + errors: [ + { line: 1, column: 18, type: "ArrowFunctionExpression", message: "Unexpected object literal returned from blockless arrow body." } + ] + }, + { + code: "var foo = () => { return 0 };", + parserOptions: { ecmaVersion: 6 }, + options: ["except-object"], + errors: [ + { line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." } + ] } ] });