Skip to content
Permalink
Browse files

Update: enforceForSequenceExpressions to no-extra-parens (fixes #11916)…

… (#12142)
  • Loading branch information
mdjermanovic authored and btmills committed Aug 30, 2019
1 parent aab1b84 commit 020f9526b618a191566acea3e17e20815d484c58
Showing with 152 additions and 22 deletions.
  1. +15 −0 docs/rules/no-extra-parens.md
  2. +8 −1 lib/rules/no-extra-parens.js
  3. +129 −21 tests/lib/rules/no-extra-parens.js
@@ -24,6 +24,7 @@ This rule has an object option for exceptions to the `"all"` option:
* `"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
* `"enforceForSequenceExpressions": false` allows extra parentheses around sequence expressions

### all

@@ -192,6 +193,20 @@ const b = a => 1 ? 2 : 3;
const d = c => (1 ? 2 : 3);
```

### enforceForSequenceExpressions

Examples of **correct** code for this rule with the `"all"` and `{ "enforceForSequenceExpressions": false }` options:

```js
/* eslint no-extra-parens: ["error", "all", { "enforceForSequenceExpressions": false }] */
(a, b);
if ((val = foo(), val < 10)) {}
while ((val = foo(), val < 10));
```

### functions

Examples of **incorrect** code for this rule with the `"functions"` option:
@@ -49,7 +49,8 @@ module.exports = {
nestedBinaryExpressions: { type: "boolean" },
returnAssign: { type: "boolean" },
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] },
enforceForArrowConditionals: { type: "boolean" }
enforceForArrowConditionals: { type: "boolean" },
enforceForSequenceExpressions: { type: "boolean" }
},
additionalProperties: false
}
@@ -77,6 +78,8 @@ module.exports = {
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 IGNORE_SEQUENCE_EXPRESSIONS = ALL_NODES && context.options[1] &&
context.options[1].enforceForSequenceExpressions === false;

const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
@@ -115,6 +118,10 @@ module.exports = {
}
}

if (node.type === "SequenceExpression" && IGNORE_SEQUENCE_EXPRESSIONS) {
return false;
}

return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
}

@@ -439,6 +439,12 @@ ruleTester.run("no-extra-parens", rule, {
{ code: "var a = b => 1 ? 2 : 3", options: ["all", { enforceForArrowConditionals: false }] },
{ code: "var a = (b) => (1 ? 2 : 3)", options: ["all", { enforceForArrowConditionals: false }] },

// ["all", { enforceForSequenceExpressions: false }]
{ code: "(a, b)", options: ["all", { enforceForSequenceExpressions: false }] },
{ code: "(foo(), bar());", options: ["all", { enforceForSequenceExpressions: false }] },
{ code: "if((a, b)){}", options: ["all", { enforceForSequenceExpressions: false }] },
{ code: "while ((val = foo(), val < 10));", options: ["all", { enforceForSequenceExpressions: false }] },

"let a = [ ...b ]",
"let a = { ...b }",
{
@@ -836,7 +842,7 @@ ruleTester.run("no-extra-parens", rule, {
options: ["all", { returnAssign: false }],
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -846,7 +852,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "function a(b) { return (b = c) || (d = e); }",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -856,7 +862,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "function a(b) { return b = 1; }",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -866,11 +872,11 @@ ruleTester.run("no-extra-parens", rule, {
output: "function a(b) { return c ? d = b : e = b; }",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
},
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -882,7 +888,7 @@ ruleTester.run("no-extra-parens", rule, {

errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -892,7 +898,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => (b = c) || (d = e);",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -902,7 +908,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => b = 1;",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -912,11 +918,11 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => c ? d = b : e = b;",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
},
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -927,7 +933,7 @@ ruleTester.run("no-extra-parens", rule, {
options: ["all", { returnAssign: false }],
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -937,7 +943,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => { return (b = c) || (d = e) };",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "LogicalExpression"
}
]
@@ -947,7 +953,7 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => { return b = 1 };",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -957,11 +963,11 @@ ruleTester.run("no-extra-parens", rule, {
output: "b => { return c ? d = b : e = b; }",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
},
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AssignmentExpression"
}
]
@@ -973,11 +979,11 @@ ruleTester.run("no-extra-parens", rule, {
output: "async function a() { await a + await b; }",
errors: [
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AwaitExpression"
},
{
messgeId: "unexpected",
messageId: "unexpected",
type: "AwaitExpression"
}
]
@@ -1058,7 +1064,7 @@ ruleTester.run("no-extra-parens", rule, {
options: ["all", { enforceForArrowConditionals: true }],
errors: [
{
messgeId: "unexpected"
messageId: "unexpected"
}
]
},
@@ -1070,7 +1076,75 @@ ruleTester.run("no-extra-parens", rule, {
options: ["all", { enforceForArrowConditionals: false }],
errors: [
{
messgeId: "unexpected"
messageId: "unexpected"
}
]
},

// ["all", { enforceForSequenceExpressions: true }]
{
code: "(a, b)",
output: "a, b",
options: ["all"],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
{
code: "(a, b)",
output: "a, b",
options: ["all", {}],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
{
code: "(a, b)",
output: "a, b",
options: ["all", { enforceForSequenceExpressions: true }],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
{
code: "(foo(), bar());",
output: "foo(), bar();",
options: ["all", { enforceForSequenceExpressions: true }],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
{
code: "if((a, b)){}",
output: "if(a, b){}",
options: ["all", { enforceForSequenceExpressions: true }],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
{
code: "while ((val = foo(), val < 10));",
output: "while (val = foo(), val < 10);",
options: ["all", { enforceForSequenceExpressions: true }],
errors: [
{
messageId: "unexpected",
type: "SequenceExpression"
}
]
},
@@ -1360,6 +1434,15 @@ ruleTester.run("no-extra-parens", rule, {
}
]
},
{
code: "for (let [a = (b in c)] = []; ;);",
output: "for (let [a = b in c] = []; ;);",
errors: [
{
messageId: "unexpected"
}
]
},
{
code: "for (let [a = b && (c in d)] = []; ;);",
output: "for (let [a = b && c in d] = []; ;);",
@@ -1414,6 +1497,15 @@ ruleTester.run("no-extra-parens", rule, {
}
]
},
{
code: "for (let { a = (b in c) } = {}; ;);",
output: "for (let { a = b in c } = {}; ;);",
errors: [
{
messageId: "unexpected"
}
]
},
{
code: "for (let { a = b && (c in d) } = {}; ;);",
output: "for (let { a = b && c in d } = {}; ;);",
@@ -1432,6 +1524,15 @@ ruleTester.run("no-extra-parens", rule, {
}
]
},
{
code: "for (let a = `${(a in b)}`; ;);",
output: "for (let a = `${a in b}`; ;);",
errors: [
{
messageId: "unexpected"
}
]
},
{
code: "for (let a = `${a && (b in c)}`; ;);",
output: "for (let a = `${a && b in c}`; ;);",
@@ -1441,6 +1542,15 @@ ruleTester.run("no-extra-parens", rule, {
}
]
},
{
code: "for (let a = (b = (c in d)) => {}; ;);",
output: "for (let a = (b = c in d) => {}; ;);",
errors: [
{
messageId: "unexpected"
}
]
},
{
code: "for (let a = (b = c && (d in e)) => {}; ;);",
output: "for (let a = (b = c && d in e) => {}; ;);",
@@ -1703,8 +1813,6 @@ ruleTester.run("no-extra-parens", rule, {
)
},

// TODO: Add '`in` inside a for-loop' first level tests for AssignmentPattern (param, obj, ary) and TemplateLiteral when these become supported.

// https://github.com/eslint/eslint/issues/11706 regression tests (also in valid[])
{
code: "for (let a = (b); a > (b); a = (b)) a = (b); a = (b);",

0 comments on commit 020f952

Please sign in to comment.
You can’t perform that action at this time.