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

Update: Option for object literals in arrow-body-style (fixes #5936) #6216

Merged
merged 1 commit into from Jun 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 24 additions & 2 deletions docs/rules/arrow-body-style.md
Expand Up @@ -8,13 +8,13 @@ This rule can enforce or disallow the use of braces around arrow function body.

## Options

The rule takes one option, a string, which can be:
The rule takes one or two options. The first is a string, which can be:

* `"always"` enforces braces around the function body
* `"as-needed"` enforces no braces where they can be omitted (default)
* `"never"` enforces no braces around the function body (constrains arrow functions to the role of returning an expression)

### "always"
The second one is an object for more fine-grained configuration when the first option is `"as-needed"`. Currently, the only available option is `requireReturnForObjectLiteral`, a boolean property. It's `false` by default. If set to `true`, it requires braces and an explicit return for object literals.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finer-grained?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it requires braces and an explicit return for object literals.

it requires braces for the function body and an explicit return when the return value is just an object literal

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BYK I am not a native english speaker, so I'm not completely sure what's better, but we use the expression "more fine-grained" in 3 other rules.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was just a suggestion so okay to leave it that way ;)


```json
"arrow-body-style": ["error", "always"]
Expand Down Expand Up @@ -84,6 +84,28 @@ let foo = () => { /* do nothing */ };
let foo = () => {
// do nothing.
};
let foo = () => ({ bar: 0 });
```

#### requireReturnForObjectLiteral

When the rule is set to `"as-needed", { requireReturnForObjectLiteral: true }` the following patterns are considered problems:

```js
/*eslint arrow-body-style: ["error", "as-needed", { requireReturnForObjectLiteral: true }]*/
/*eslint-env es6*/
let foo = () => ({});
let foo = () => ({ bar: 0 });
```

The following patterns are not considered problems:

```js
/*eslint arrow-body-style: ["error", "as-needed", { requireReturnForObjectLiteral: true }]*/
/*eslint-env es6*/

let foo = () => {};
let foo = () => { return { bar: 0 }; };
```

### "never"
Expand Down
51 changes: 42 additions & 9 deletions lib/rules/arrow-body-style.js
Expand Up @@ -16,17 +16,45 @@ module.exports = {
recommended: false
},

schema: [
{
enum: ["always", "as-needed", "never"]
}
]
schema: {
anyOf: [
{
type: "array",
items: [
{
enum: ["always", "never"]
}
],
minItems: 0,
maxItems: 1
},
{
type: "array",
items: [
{
enum: ["as-needed"]
},
{
type: "object",
properties: {
requireReturnForObjectLiteral: {type: "boolean"}
},
additionalProperties: false
}
],
minItems: 0,
maxItems: 2
}
]
}
},

create: function(context) {
var always = context.options[0] === "always";
var asNeeded = !context.options[0] || context.options[0] === "as-needed";
var never = context.options[0] === "never";
var options = context.options;
var always = options[0] === "always";
var asNeeded = !options[0] || options[0] === "as-needed";
var never = options[0] === "never";
var requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral;

/**
* Determines whether a arrow function body needs braces
Expand All @@ -50,6 +78,11 @@ module.exports = {
return;
}

if (asNeeded && requireReturnForObjectLiteral && blockBody[0].type === "ReturnStatement" &&
blockBody[0].argument.type === "ObjectExpression") {
return;
}

if (asNeeded && blockBody[0].type === "ReturnStatement") {
context.report({
node: node,
Expand All @@ -59,7 +92,7 @@ module.exports = {
}
}
} else {
if (always) {
if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) {
context.report({
node: node,
loc: arrowBody.loc.start,
Expand Down
53 changes: 52 additions & 1 deletion tests/lib/rules/arrow-body-style.js
Expand Up @@ -26,13 +26,24 @@ ruleTester.run("arrow-body-style", rule, {
{ code: "var foo = () => {\n /* do nothing */ \n};", parserOptions: { ecmaVersion: 6 } },
{ code: "var foo = (retv, name) => {\nretv[name] = true;\nreturn retv;\n};", parserOptions: { ecmaVersion: 6 } },
{ code: "var foo = () => ({});", parserOptions: { ecmaVersion: 6 } },
{ code: "var foo = () => bar();", parserOptions: { ecmaVersion: 6 } },
{ code: "var foo = () => { bar(); };", parserOptions: { ecmaVersion: 6 } },
{ 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 = () => 0;", parserOptions: { ecmaVersion: 6 }, options: ["never"] },
{ code: "var foo = () => ({ foo: 0 });", parserOptions: { ecmaVersion: 6 }, options: ["never"] }
{ code: "var foo = () => ({ foo: 0 });", parserOptions: { ecmaVersion: 6 }, options: ["never"] },
{ code: "var foo = () => {};", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => 0;", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var addToB = (a) => { b = b + a };", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => { /* do nothing */ };", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => {\n /* do nothing */ \n};", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = (retv, name) => {\nretv[name] = true;\nreturn retv;\n};", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => bar();", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => { bar(); };", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var addToB = (a) => { b = b + a };", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] },
{ code: "var foo = () => { return { bar: 0 }; };", parserOptions: { ecmaVersion: 6 }, options: ["as-needed", {requireReturnForObjectLiteral: true }] }
],
invalid: [
{
Expand Down Expand Up @@ -75,13 +86,53 @@ ruleTester.run("arrow-body-style", rule, {
{ line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." }
]
},
{
code: "var foo = () => { return { bar: 0 }; };",
parserOptions: { ecmaVersion: 6 },
options: ["as-needed"],
errors: [
{ line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." }
]
},
{
code: "var foo = (retv, name) => {\nretv[name] = true;\nreturn retv;\n};",
parserOptions: { ecmaVersion: 6 },
options: ["never"],
errors: [
{ line: 1, column: 27, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." }
]
},
{
code: "var foo = () => { return 0; };",
parserOptions: { ecmaVersion: 6 },
options: ["as-needed", {requireReturnForObjectLiteral: true }],
errors: [
{ line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." }
]
},
{
code: "var foo = () => { return bar(); };",
parserOptions: { ecmaVersion: 6 },
options: ["as-needed", {requireReturnForObjectLiteral: true }],
errors: [
{ line: 1, column: 17, type: "ArrowFunctionExpression", message: "Unexpected block statement surrounding arrow body." }
]
},
{
code: "var foo = () => ({});",
parserOptions: { ecmaVersion: 6 },
options: ["as-needed", {requireReturnForObjectLiteral: true }],
errors: [
{ line: 1, column: 18, type: "ArrowFunctionExpression", message: "Expected block statement surrounding arrow body." }
]
},
{
code: "var foo = () => ({ bar: 0 });",
parserOptions: { ecmaVersion: 6 },
options: ["as-needed", {requireReturnForObjectLiteral: true }],
errors: [
{ line: 1, column: 18, type: "ArrowFunctionExpression", message: "Expected block statement surrounding arrow body." }
]
}
]
});