diff --git a/docs/rules/no-extra-parens.md b/docs/rules/no-extra-parens.md index 0a358388295..b30b217a078 100644 --- a/docs/rules/no-extra-parens.md +++ b/docs/rules/no-extra-parens.md @@ -22,6 +22,7 @@ This rule has an object option for exceptions to the `"all"` option: * `"returnAssign": false` allows extra parentheses around assignments in `return` statements * `"nestedBinaryExpressions": false` allows extra parentheses in nested binary expressions * `"ignoreJSX": "none|all|multi-line|single-line"` allows extra parentheses around no/all/multi-line/single-line JSX components. Defaults to `none`. +* `"enforceForArrowConditionals": false` allows extra parentheses around ternary expressions which are the body of an arrow function ### all @@ -165,6 +166,17 @@ const Component = (
) const Component = (

) ``` +### enforceForArrowConditionals + +Examples of **correct** code for this rule with the `"all"` and `{ "enforceForArrowConditionals": false }` options: + +```js +/* eslint no-extra-parens: ["error", "all", { "enforceForArrowConditionals": false }] */ + +const b = a => 1 ? 2 : 3; +const d = c => (1 ? 2 : 3); +``` + ### functions Examples of **incorrect** code for this rule with the `"functions"` option: diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index d0d79c6a329..9f48f1d81a9 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -44,7 +44,8 @@ module.exports = { conditionalAssign: { type: "boolean" }, nestedBinaryExpressions: { type: "boolean" }, returnAssign: { type: "boolean" }, - ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] } + ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] }, + enforceForArrowConditionals: { type: "boolean" } }, additionalProperties: false } @@ -67,6 +68,9 @@ module.exports = { const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX; + const IGNORE_ARROW_CONDITIONALS = ALL_NODES && context.options[1] && + context.options[1].enforceForArrowConditionals === false; + const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); @@ -448,6 +452,13 @@ module.exports = { return; } + if (node.body.type === "ConditionalExpression" && + IGNORE_ARROW_CONDITIONALS && + !isParenthesisedTwice(node.body) + ) { + return; + } + if (node.body.type !== "BlockStatement") { const firstBodyToken = sourceCode.getFirstToken(node.body, astUtils.isNotOpeningParenToken); const tokenBeforeFirst = sourceCode.getTokenBefore(firstBodyToken); diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index fb69eb71343..54990b96e3a 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -368,6 +368,10 @@ ruleTester.run("no-extra-parens", rule, { "/>)" ].join("\n"), options: ["all", { ignoreJSX: "multi-line" }] }, + // ["all", { enforceForArrowConditionals: false }] + { code: "var a = b => 1 ? 2 : 3", options: ["all", { enforceForArrowConditionals: false }], parserOptions: { ecmaVersion: 6 } }, + { code: "var a = (b) => (1 ? 2 : 3)", options: ["all", { enforceForArrowConditionals: false }], parserOptions: { ecmaVersion: 6 } }, + { code: "let a = [ ...b ]", parserOptions: { ecmaVersion: 2015 } @@ -921,6 +925,32 @@ ruleTester.run("no-extra-parens", rule, { options: ["all", { ignoreJSX: "none" }] }), + // ["all", { enforceForArrowConditionals: true }] + { + code: "var a = (b) => (1 ? 2 : 3)", + parserOptions: { ecmaVersion: 6 }, + options: ["all", { enforceForArrowConditionals: true }], + errors: [ + { + message: "Gratuitous parentheses around expression." + } + ], + output: "var a = (b) => 1 ? 2 : 3" + }, + + // ["all", { enforceForArrowConditionals: false }] + { + code: "var a = (b) => ((1 ? 2 : 3))", + parserOptions: { ecmaVersion: 6 }, + options: ["all", { enforceForArrowConditionals: false }], + errors: [ + { + message: "Gratuitous parentheses around expression." + } + ], + output: "var a = (b) => (1 ? 2 : 3)" + }, + // https://github.com/eslint/eslint/issues/8175 invalid( "let a = [...(b)]",