From b51d0778d76c2aa27578caca3ea82c867dced3e4 Mon Sep 17 00:00:00 2001 From: t-mangoe Date: Sun, 4 Apr 2021 06:30:13 +0900 Subject: [PATCH] Update: add ignoreNonDeclaration to no-multi-assign rule (fixes #12545) (#14185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update: add an option to ignore non declaration (refs #12545) * Doc: add description of the option (refs #12545) * Chore: reflect review comments (refs #12545) * Chore: modify the document according to comments (refs #12545) --- docs/rules/no-multi-assign.md | 32 ++++++++++++++++++++++++++ lib/rules/no-multi-assign.js | 17 ++++++++++++-- tests/lib/rules/no-multi-assign.js | 37 +++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/docs/rules/no-multi-assign.md b/docs/rules/no-multi-assign.md index 41bba9ad6a9..7ef70567593 100644 --- a/docs/rules/no-multi-assign.md +++ b/docs/rules/no-multi-assign.md @@ -43,6 +43,38 @@ let a = c; let b = c; ``` +## Options + +This rule has an object option: + +* `"ignoreNonDeclaration"`: When set to `true`, the rule allows chains that don't include initializing a variable in a declaration. Default is `false`. + +### ignoreNonDeclaration + +Examples of **correct** code for the `{ "ignoreNonDeclaration": true }` option: + +```js +/*eslint no-multi-assign: ["error", { "ignoreNonDeclaration": true }]*/ + +let a; +let b; +a = b = "baz"; + +const x = {}; +const y = {}; +x.one = y.one = 1; +``` + +Examples of **incorrect** code for the `{ "ignoreNonDeclaration": true }` option: + +```js +/*eslint no-multi-assign: ["error", { "ignoreNonDeclaration": true }]*/ + +let a = b = "baz"; + +const foo = bar = 1; +``` + ## Related Rules * [max-statements-per-line](max-statements-per-line.md) diff --git a/lib/rules/no-multi-assign.js b/lib/rules/no-multi-assign.js index ab6430c19ef..d2606a1502a 100644 --- a/lib/rules/no-multi-assign.js +++ b/lib/rules/no-multi-assign.js @@ -21,7 +21,16 @@ module.exports = { url: "https://eslint.org/docs/rules/no-multi-assign" }, - schema: [], + schema: [{ + type: "object", + properties: { + ignoreNonDeclaration: { + type: "boolean", + default: false + } + }, + additionalProperties: false + }], messages: { unexpectedChain: "Unexpected chained assignment." @@ -33,10 +42,14 @@ module.exports = { //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- + const options = context.options[0] || { + ignoreNonDeclaration: false + }; + const targetParent = options.ignoreNonDeclaration ? ["VariableDeclarator"] : ["AssignmentExpression", "VariableDeclarator"]; return { AssignmentExpression(node) { - if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) { + if (targetParent.indexOf(node.parent.type) !== -1) { context.report({ node, messageId: "unexpectedChain" diff --git a/tests/lib/rules/no-multi-assign.js b/tests/lib/rules/no-multi-assign.js index dc907465c60..c534f55b33f 100644 --- a/tests/lib/rules/no-multi-assign.js +++ b/tests/lib/rules/no-multi-assign.js @@ -51,7 +51,9 @@ ruleTester.run("no-mutli-assign", rule, { { code: "for(let a = 0, b = 0;;){}", parserOptions: { ecmaVersion: 6 } }, { code: "for(const a = 0, b = 0;;){}", parserOptions: { ecmaVersion: 6 } }, { code: "export let a, b;", parserOptions: { ecmaVersion: 6, sourceType: "module" } }, - { code: "export let a,\n b = 0;", parserOptions: { ecmaVersion: 6, sourceType: "module" } } + { code: "export let a,\n b = 0;", parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { code: "const x = {};const y = {};x.one = y.one = 1;", options: [{ ignoreNonDeclaration: true }], parserOptions: { ecmaVersion: 6 } }, + { code: "let a, b;a = b = 1", options: [{ ignoreNonDeclaration: true }], parserOptions: { ecmaVersion: 6 } } ], invalid: [ @@ -137,6 +139,39 @@ ruleTester.run("no-mutli-assign", rule, { errors: [ errorAt(1, 5, "AssignmentExpression") ] + }, + { + code: "const x = {};\nconst y = x.one = 1;", + options: [{ ignoreNonDeclaration: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + errorAt(2, 11, "AssignmentExpression") + ] + + }, + { + code: "let a, b;a = b = 1", + options: [{}], + parserOptions: { ecmaVersion: 6 }, + errors: [ + errorAt(1, 14, "AssignmentExpression") + ] + }, + { + code: "let x, y;x = y = 'baz'", + options: [{ ignoreNonDeclaration: false }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + errorAt(1, 14, "AssignmentExpression") + ] + }, + { + code: "const a = b = 1", + options: [{ ignoreNonDeclaration: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [ + errorAt(1, 11, "AssignmentExpression") + ] } ] });