Skip to content

Commit

Permalink
Update: add option "allowInParentheses" to no-sequences (fixes #14197) (
Browse files Browse the repository at this point in the history
#14199)

* New: add option "allowInParentheses" to rule "no-sequences"

* added documentation

* [no-equence]: switch default of "allowInParentheses" to true

* restored removed sentence

* changes from code review

* code review
  • Loading branch information
danielrentz committed Mar 26, 2021
1 parent dbf2529 commit 687ccae
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 13 deletions.
42 changes: 40 additions & 2 deletions docs/rules/no-sequences.md
Expand Up @@ -17,7 +17,7 @@ while (a = next(), a && a.length);
This rule forbids the use of the comma operator, with the following exceptions:

* In the initialization or update portions of a `for` statement.
* If the expression sequence is explicitly wrapped in parentheses.
* By default, if the expression sequence is explicitly wrapped in parentheses. This exception can be removed with the `allowInParentheses` option.

Examples of **incorrect** code for this rule:

Expand Down Expand Up @@ -63,10 +63,48 @@ while ((val = foo(), val < 42));
with ((doSomething(), val)) {}
```

## Options

This rule takes one option, an object, with the following properties:

* `"allowInParentheses"`: If set to `true` (default), this rule allows expression sequences that are explicitly wrapped in parentheses.

### allowInParentheses

Examples of **incorrect** code for this rule with the `{ "allowInParentheses": false }` option:

```js
/*eslint no-sequences: ["error", { "allowInParentheses": false }]*/

foo = (doSomething(), val);

(0, eval)("doSomething();");

do {} while ((doSomething(), !!test));

for (; (doSomething(), !!test); );

if ((doSomething(), !!test));

switch ((val = foo(), val)) {}

while ((val = foo(), val < 42));

with ((doSomething(), val)) {}
```

Examples of **correct** code for this rule with the `{ "allowInParentheses": false }` option:

```js
/*eslint no-sequences: ["error", { "allowInParentheses": false }]*/

for (i = 0, j = 10; i < j; i++, j--);
```

## When Not To Use It

Disable this rule if sequence expressions with the comma operator are acceptable.
Another case is where you might want to report all usages of the comma operator, even if they are wrapped in parentheses or in a for loop. You can achieve this using rule `no-restricted-syntax`:
Another case is where you might want to report all usages of the comma operator, even in a for loop. You can achieve this using rule `no-restricted-syntax`:

```js
{
Expand Down
35 changes: 27 additions & 8 deletions lib/rules/no-sequences.js
Expand Up @@ -11,6 +11,14 @@

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const DEFAULT_OPTIONS = {
allowInParentheses: true
};

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand All @@ -26,14 +34,23 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-sequences"
},

schema: [],
schema: [{
properties: {
allowInParentheses: {
type: "boolean",
default: true
}
},
additionalProperties: false
}],

messages: {
unexpectedCommaExpression: "Unexpected use of comma operator."
}
},

create(context) {
const options = Object.assign({}, DEFAULT_OPTIONS, context.options[0]);
const sourceCode = context.getSourceCode();

/**
Expand Down Expand Up @@ -99,13 +116,15 @@ module.exports = {
}

// Wrapping a sequence in extra parens indicates intent
if (requiresExtraParens(node)) {
if (isParenthesisedTwice(node)) {
return;
}
} else {
if (isParenthesised(node)) {
return;
if (options.allowInParentheses) {
if (requiresExtraParens(node)) {
if (isParenthesisedTwice(node)) {
return;
}
} else {
if (isParenthesised(node)) {
return;
}
}
}

Expand Down
28 changes: 25 additions & 3 deletions tests/lib/rules/no-sequences.js
Expand Up @@ -46,10 +46,20 @@ ruleTester.run("no-sequences", rule, {
"do {} while ((doSomething(), !!test));",
"for ((doSomething(), somethingElse()); (doSomething(), !!test); );",
"if ((doSomething(), !!test));",
"switch ((doSomething(), !!test)) {}",
"switch ((doSomething(), val)) {}",
"while ((doSomething(), !!test));",
"with ((doSomething(), val)) {}",
{ code: "a => ((doSomething(), a))", env: { es6: true } }
{ code: "a => ((doSomething(), a))", env: { es6: true } },

// options object without "allowInParentheses" property
{ code: "var foo = (1, 2);", options: [{}] },

// explicitly set option "allowInParentheses" to default value
{ code: "var foo = (1, 2);", options: [{ allowInParentheses: true }] },

// valid code with "allowInParentheses" set to `false`
{ code: "for ((i = 0, j = 0); test; );", options: [{ allowInParentheses: false }] },
{ code: "for (; test; (i++, j++));", options: [{ allowInParentheses: false }] }
],

// Examples of code that should trigger the rule
Expand All @@ -75,6 +85,18 @@ ruleTester.run("no-sequences", rule, {
{ code: "a => (doSomething(), a)", env: { es6: true }, errors: errors(20) },
{ code: "(1), 2", errors: errors(4) },
{ code: "((1)) , (2)", errors: errors(7) },
{ code: "while((1) , 2);", errors: errors(11) }
{ code: "while((1) , 2);", errors: errors(11) },

// option "allowInParentheses": do not allow sequence in parentheses
{ code: "var foo = (1, 2);", options: [{ allowInParentheses: false }], errors: errors(13) },
{ code: "(0,eval)(\"foo()\");", options: [{ allowInParentheses: false }], errors: errors(3) },
{ code: "foo(a, (b, c), d);", options: [{ allowInParentheses: false }], errors: errors(10) },
{ code: "do {} while ((doSomething(), !!test));", options: [{ allowInParentheses: false }], errors: errors(28) },
{ code: "for (; (doSomething(), !!test); );", options: [{ allowInParentheses: false }], errors: errors(22) },
{ code: "if ((doSomething(), !!test));", options: [{ allowInParentheses: false }], errors: errors(19) },
{ code: "switch ((doSomething(), val)) {}", options: [{ allowInParentheses: false }], errors: errors(23) },
{ code: "while ((doSomething(), !!test));", options: [{ allowInParentheses: false }], errors: errors(22) },
{ code: "with ((doSomething(), val)) {}", options: [{ allowInParentheses: false }], errors: errors(21) },
{ code: "a => ((doSomething(), a))", options: [{ allowInParentheses: false }], env: { es6: true }, errors: errors(21) }
]
});

0 comments on commit 687ccae

Please sign in to comment.