From 908899357a0c71163d5c8d8b8d8cee73aeb2dd6d Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 29 Oct 2019 03:11:14 +0100 Subject: [PATCH 1/4] New: Add no-dupe-else-if rule (fixes #12469) --- docs/rules/no-dupe-else-if.md | 130 ++++++++++++++++++++++ lib/rules/index.js | 1 + lib/rules/no-dupe-else-if.js | 54 +++++++++ tests/lib/rules/no-dupe-else-if.js | 172 +++++++++++++++++++++++++++++ tools/rule-types.json | 1 + 5 files changed, 358 insertions(+) create mode 100644 docs/rules/no-dupe-else-if.md create mode 100644 lib/rules/no-dupe-else-if.js create mode 100644 tests/lib/rules/no-dupe-else-if.js diff --git a/docs/rules/no-dupe-else-if.md b/docs/rules/no-dupe-else-if.md new file mode 100644 index 00000000000..2f568b3a672 --- /dev/null +++ b/docs/rules/no-dupe-else-if.md @@ -0,0 +1,130 @@ +# Disallow duplicate conditions in `if-else-if` chains (no-dupe-else-if) + +`if-else-if` chains are commonly used when there is a need to execute only one branch or at most one branch out of several possible branches, based on certain conditions. + +```js +if (a) { + foo(); +} else if (b) { + bar(); +} else if (c) { + baz(); +} +``` + +Two identical test conditions in the same chain are almost always a mistake in the code. Unless there are side effects in the expressions, a duplicate will evaluate to the same `true` or `false` value as the identical expression earlier in the chain, meaning that its branch can never execute. + +```js +if (a) { + foo(); +} else if (b) { + bar(); +} else if (b) { + baz(); +} +``` + +In the above example, `baz()` can never execute. Obviously, `baz()` could be executed only when `b` evaluates to `true`, but in that case `bar()` would be executed instead, since it's earlier in the chain. + +## Rule Details + +This rule disallows duplicate conditions in the same `if-else-if` chain. + +Examples of **incorrect** code for this rule: + +```js +/*eslint no-dupe-else-if: "error"*/ + +if (isSomething(x)) { + foo(); +} else if (isSomething(x)) { + bar(); +} + +if (a) { + foo(); +} else if (b) { + bar(); +} else if (c && d) { + baz(); +} else if (c && d) { + quux(); +} else { + quuux(); +} + +if (n === 1) { + foo(); +} else if (n === 2) { + bar(); +} else if (n === 3) { + baz(); +} else if (n === 2) { + quux(); +} else if (n === 5) { + quuux(); +} +``` + +Examples of **correct** code for this rule: + +```js +/*eslint no-dupe-else-if: "error"*/ + +if (isSomething(x)) { + foo(); +} else if (isSomethingElse(x)) { + bar(); +} + +if (a) { + foo(); +} else if (b) { + bar(); +} else if (c && d) { + baz(); +} else if (c && e) { + quux(); +} else { + quuux(); +} + +if (n === 1) { + foo(); +} else if (n === 2) { + bar(); +} else if (n === 3) { + baz(); +} else if (n === 4) { + quux(); +} else if (n === 5) { + quuux(); +} +``` + +Please note that this rule does not compare conditions from the chain with conditions inside statements, and will not warn in the cases such as follows: + +```js +if (a) { + if (a) { + foo(); + } +} + +if (a) { + foo(); +} else { + if (a) { + bar(); + } +} +``` + +## When Not To Use It + +In rare cases where you really need identical test conditions in the same chain, which necessarily means that the expressions in the chain are causing and relying on side effects, you will have to turn this rule off. + +## Related Rules + +* [no-duplicate-case](no-duplicate-case.md) +* [no-lonely-if](no-lonely-if.md) diff --git a/lib/rules/index.js b/lib/rules/index.js index 8b0abc4ee7a..196e466ab91 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -108,6 +108,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "no-div-regex": () => require("./no-div-regex"), "no-dupe-args": () => require("./no-dupe-args"), "no-dupe-class-members": () => require("./no-dupe-class-members"), + "no-dupe-else-if": () => require("./no-dupe-else-if"), "no-dupe-keys": () => require("./no-dupe-keys"), "no-duplicate-case": () => require("./no-duplicate-case"), "no-duplicate-imports": () => require("./no-duplicate-imports"), diff --git a/lib/rules/no-dupe-else-if.js b/lib/rules/no-dupe-else-if.js new file mode 100644 index 00000000000..e1c4688432f --- /dev/null +++ b/lib/rules/no-dupe-else-if.js @@ -0,0 +1,54 @@ +/** + * @fileoverview Rule to disallow duplicate conditions in if-else-if chains + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow duplicate conditions in if-else-if chains", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/no-dupe-else-if" + }, + + schema: [], + + messages: { + unexpected: "Duplicate condition in if-else-if chain." + } + }, + + create(context) { + const sourceCode = context.getSourceCode(); + + return { + IfStatement(node) { + let current = node; + + while (current.parent && current.parent.type === "IfStatement" && current.parent.alternate === current) { + current = current.parent; + + if (astUtils.equalTokens(node.test, current.test, sourceCode)) { + context.report({ node: node.test, messageId: "unexpected" }); + break; + } + } + } + }; + } +}; diff --git a/tests/lib/rules/no-dupe-else-if.js b/tests/lib/rules/no-dupe-else-if.js new file mode 100644 index 00000000000..ee60dc32186 --- /dev/null +++ b/tests/lib/rules/no-dupe-else-if.js @@ -0,0 +1,172 @@ +/** + * @fileoverview Tests for the no-dupe-else-if rule + * @author Milos Djermanovic + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-dupe-else-if"); +const { RuleTester } = require("../../../lib/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("no-dupe-else-if", rule, { + valid: [ + + // different test conditions + "if (a) {} else if (b) {}", + "if (a); else if (b); else if (c);", + "if (true) {} else if (false) {} else {}", + "if (1) {} else if (2) {}", + "if (f) {} else if (f()) {}", + "if (f(a)) {} else if (g(a)) {}", + "if (f(a)) {} else if (f(b)) {}", + "if (a === 1) {} else if (a === 2) {}", + "if (a === 1) {} else if (b === 1) {}", + + // not an if-else-if chain + "if (a) {}", + "if (a);", + "if (a) {} else {}", + "if (a) if (a) {}", + "if (a) if (a);", + "if (a) { if (a) {} }", + "if (a) {} else { if (a) {} }", + "if (a) {} if (a) {}", + "if (a); if (a);", + "while (a) if (a);", + "if (a); else a ? a : a;", + + // not same conditions in the chain + "if (a) { if (b) {} } else if (b) {}", + "if (a) if (b); else if (a);", + + // not equal tokens + "if (a) {} else if (!!a) {}", + "if (a === 1) {} else if (a === (1)) {}" + ], + + invalid: [ + + // basic tests + { + code: "if (a) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 20 }] + }, + { + code: "if (a); else if (a);", + errors: [{ messageId: "unexpected", type: "Identifier", column: 18 }] + }, + { + code: "if (a) {} else if (a) {} else {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 20 }] + }, + { + code: "if (a) {} else if (b) {} else if (a) {} else if (c) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 35 }] + }, + { + code: "if (a) {} else if (b) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 35 }] + }, + { + code: "if (a) {} else if (b) {} else if (c) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 50 }] + }, + { + code: "if (a) {} else if (b) {} else if (b) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 35 }] + }, + { + code: "if (a) {} else if (b) {} else if (b) {} else {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 35 }] + }, + { + code: "if (a) {} else if (b) {} else if (c) {} else if (b) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 50 }] + }, + { + code: "if (a); else if (b); else if (c); else if (b); else if (d); else;", + errors: [{ messageId: "unexpected", type: "Identifier", column: 44 }] + }, + { + code: "if (a); else if (b); else if (c); else if (d); else if (b); else if (e);", + errors: [{ messageId: "unexpected", type: "Identifier", column: 57 }] + }, + + // multiple duplicates of the same condition + { + code: "if (a) {} else if (a) {} else if (a) {}", + errors: [ + { messageId: "unexpected", type: "Identifier", column: 20 }, + { messageId: "unexpected", type: "Identifier", column: 35 } + ] + }, + + // multiple duplicates of different conditions + { + code: "if (a) {} else if (b) {} else if (a) {} else if (b) {} else if (a) {}", + errors: [ + { messageId: "unexpected", type: "Identifier", column: 35 }, + { messageId: "unexpected", type: "Identifier", column: 50 }, + { messageId: "unexpected", type: "Identifier", column: 65 } + ] + }, + + // inner if statements do not affect chain + { + code: "if (a) { if (b) {} } else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 31 }] + }, + + // various kinds of test conditions + { + code: "if (a === 1) {} else if (a === 1) {}", + errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 26 }] + }, + { + code: "if (1 < a) {} else if (1 < a) {}", + errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 24 }] + }, + { + code: "if (true) {} else if (true) {}", + errors: [{ messageId: "unexpected", type: "Literal", column: 23 }] + }, + { + code: "if (a && b) {} else if (a && b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a && b || c) {} else if (a && b || c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 31 }] + }, + { + code: "if (f(a)) {} else if (f(a)) {}", + errors: [{ messageId: "unexpected", type: "CallExpression", column: 23 }] + }, + + // spaces and comments do not affect comparison + { + code: "if (a === 1) {} else if (a===1) {}", + errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 26 }] + }, + { + code: "if (a === 1) {} else if (a === /* comment */ 1) {}", + errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 26 }] + }, + + // extra parens around the whole test condition do not affect comparison + { + code: "if (a === 1) {} else if ((a === 1)) {}", + errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 27 }] + } + ] +}); diff --git a/tools/rule-types.json b/tools/rule-types.json index 6c72abb6cb2..518b459d736 100644 --- a/tools/rule-types.json +++ b/tools/rule-types.json @@ -95,6 +95,7 @@ "no-div-regex": "suggestion", "no-dupe-args": "problem", "no-dupe-class-members": "problem", + "no-dupe-else-if": "problem", "no-dupe-keys": "problem", "no-duplicate-case": "problem", "no-duplicate-imports": "problem", From f07ea75f3729bbfa0c7b45b6d7177f536deb9f7b Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 5 Nov 2019 22:30:55 +0100 Subject: [PATCH 2/4] Add || and && logic --- docs/rules/no-dupe-else-if.md | 50 +++++++++- lib/rules/no-dupe-else-if.js | 76 ++++++++++++++- tests/lib/rules/no-dupe-else-if.js | 147 ++++++++++++++++++++++++++++- 3 files changed, 267 insertions(+), 6 deletions(-) diff --git a/docs/rules/no-dupe-else-if.md b/docs/rules/no-dupe-else-if.md index 2f568b3a672..8b91c83224b 100644 --- a/docs/rules/no-dupe-else-if.md +++ b/docs/rules/no-dupe-else-if.md @@ -1,6 +1,6 @@ # Disallow duplicate conditions in `if-else-if` chains (no-dupe-else-if) -`if-else-if` chains are commonly used when there is a need to execute only one branch or at most one branch out of several possible branches, based on certain conditions. +`if-else-if` chains are commonly used when there is a need to execute only one branch (or at most one branch) out of several possible branches, based on certain conditions. ```js if (a) { @@ -102,6 +102,54 @@ if (n === 1) { } ``` +This rule can also detect some cases where the conditions are not identical, but the branch can never execute due to the logic of `||` and `&&` operators. + +Examples of additional **incorrect** code for this rule: + +```js +/*eslint no-dupe-else-if: "error"*/ + +if (a || b) { + foo(); +} else if (a) { + bar(); +} + +if (a) { + foo(); +} else if (b) { + bar(); +} else if (a || b) { + baz(); +} + +if (a) { + foo(); +} else if (a && b) { + bar(); +} + +if (a && b) { + foo(); +} else if (a && b && c) { + bar(); +} + +if (a || b) { + foo(); +} else if (b && c) { + bar(); +} + +if (a) { + foo(); +} else if (b && c) { + bar(); +} else if (d && (c && e && b || a)) { + baz(); +} +``` + Please note that this rule does not compare conditions from the chain with conditions inside statements, and will not warn in the cases such as follows: ```js diff --git a/lib/rules/no-dupe-else-if.js b/lib/rules/no-dupe-else-if.js index e1c4688432f..9106fe466a1 100644 --- a/lib/rules/no-dupe-else-if.js +++ b/lib/rules/no-dupe-else-if.js @@ -11,6 +11,37 @@ const astUtils = require("./utils/ast-utils"); +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Determines whether the first given array is a subset of the second given array. + * @param {Function} comparator A function to compare two elements, should return `true` if they are equal. + * @param {Array} arrA The array to compare from. + * @param {Array} arrB The array to compare against. + * @returns {boolean} `true` if the array `arrA` is a subset of the array `arrB`. + */ +function isSubsetByComparator(comparator, arrA, arrB) { + return arrA.every(a => arrB.some(b => comparator(a, b))); +} + +/** + * Splits the given node by the given logical operator. + * @param {string} operator Logical operator `||` or `&&`. + * @param {ASTNode} node The node to split. + * @returns {ASTNode[]} Array of conditions that makes the node when joined by the operator. + */ +function splitByLogicalOperator(operator, node) { + if (node.type === "LogicalExpression" && node.operator === operator) { + return [...splitByLogicalOperator(operator, node.left), ...splitByLogicalOperator(operator, node.right)]; + } + return [node]; +} + +const splitByOr = splitByLogicalOperator.bind(null, "||"); +const splitByAnd = splitByLogicalOperator.bind(null, "&&"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -29,22 +60,59 @@ module.exports = { schema: [], messages: { - unexpected: "Duplicate condition in if-else-if chain." + unexpected: "This branch can never execute, its condition is a duplicate or covered by previous conditions in the if-else-if chain." } }, create(context) { const sourceCode = context.getSourceCode(); + /** + * Determines whether the two given nodes are considered to be equal. In particular, given that the nodes + * represent expressions in a boolean context, `||` and `&&` can be considered as commutative operators. + * @param {ASTNode} a First node. + * @param {ASTNode} b Second node. + * @returns {boolean} `true` if the nodes are considered to be equal. + */ + function equal(a, b) { + if (a.type !== b.type) { + return false; + } + + if ( + a.type === "LogicalExpression" && + (a.operator === "||" || a.operator === "&&") && + a.operator === b.operator + ) { + return equal(a.left, b.left) && equal(a.right, b.right) || + equal(a.left, b.right) && equal(a.right, b.left); + } + + return astUtils.equalTokens(a, b, sourceCode); + } + + const isSubset = isSubsetByComparator.bind(null, equal); + return { IfStatement(node) { - let current = node; + const test = node.test, + conditionsToCheck = test.type === "LogicalExpression" && test.operator === "&&" + ? [test, ...splitByAnd(test)] + : [test]; + let current = node, + listToCheck = conditionsToCheck.map(c => splitByOr(c).map(splitByAnd)); while (current.parent && current.parent.type === "IfStatement" && current.parent.alternate === current) { current = current.parent; - if (astUtils.equalTokens(node.test, current.test, sourceCode)) { - context.report({ node: node.test, messageId: "unexpected" }); + const currentConditions = splitByOr(current.test).map(splitByAnd); + + listToCheck = listToCheck.map(e => e.filter( + lc => !currentConditions.some(cc => isSubset(cc, lc)) + )); + + if (listToCheck.some(e => e.length === 0)) { + context.report({ node: test, messageId: "unexpected" }); break; } } diff --git a/tests/lib/rules/no-dupe-else-if.js b/tests/lib/rules/no-dupe-else-if.js index ee60dc32186..156c22fd5a0 100644 --- a/tests/lib/rules/no-dupe-else-if.js +++ b/tests/lib/rules/no-dupe-else-if.js @@ -51,7 +51,19 @@ ruleTester.run("no-dupe-else-if", rule, { // not equal tokens "if (a) {} else if (!!a) {}", - "if (a === 1) {} else if (a === (1)) {}" + "if (a === 1) {} else if (a === (1)) {}", + + // more complex valid chains (may contain redundant subconditions, but the branch can be executed) + "if (a || b) {} else if (c || d) {}", + "if (a || b) {} else if (a || c) {}", + "if (a) {} else if (a || b) {}", + "if (a) {} else if (b) {} else if (a || b || c) {}", + "if (a && b) {} else if (a) {} else if (b) {}", + "if (a && b) {} else if (b && c) {} else if (a && c) {}", + "if (a && b) {} else if (b || c) {}", + "if (a) {} else if (b && (a || c)) {}", + "if (a) {} else if (b && (c || d && a)) {}", + "if (a && b && c) {} else if (a && b && (c || d)) {}" ], invalid: [ @@ -167,6 +179,139 @@ ruleTester.run("no-dupe-else-if", rule, { { code: "if (a === 1) {} else if ((a === 1)) {}", errors: [{ messageId: "unexpected", type: "BinaryExpression", column: 27 }] + }, + + // more complex errors with `||` and `&&` + { + code: "if (a || b) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 25 }] + }, + { + code: "if (a || b) {} else if (a) {} else if (b) {}", + errors: [ + { messageId: "unexpected", type: "Identifier", column: 25 }, + { messageId: "unexpected", type: "Identifier", column: 40 } + ] + }, + { + code: "if (a || b) {} else if (b || a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a) {} else if (b) {} else if (a || b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if (a || b) {} else if (c || d) {} else if (a || d) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 45 }] + }, + { + code: "if ((a === b && fn(c)) || d) {} else if (fn(c) && a === b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 42 }] + }, + { + code: "if (a) {} else if (a && b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 20 }] + }, + { + code: "if (a && b) {} else if (b && a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a && b) {} else if (a && b && c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a || c) {} else if (a && b || c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a) {} else if (b) {} else if (c && a || b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if (a) {} else if (b) {} else if (c && (a || b)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if (a) {} else if (b && c) {} else if (d && (a || e && c && b)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 40 }] + }, + { + code: "if (a || b && c) {} else if (b && c && d) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 30 }] + }, + { + code: "if (a || b) {} else if (b && c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a) {} else if (b) {} else if ((a || b) && c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if ((a && (b || c)) || d) {} else if ((c || b) && e && a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 39 }] + }, + { + code: "if (a && b || b && c) {} else if (a && b && c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if (a) {} else if (b && c) {} else if (d && (c && e && b || a)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 40 }] + }, + { + code: "if (a || (b && (c || d))) {} else if ((d || c) && b) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 39 }] + }, + { + code: "if (a || b) {} else if ((b || a) && c) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a || b) {} else if (c) {} else if (d) {} else if (b && (a || c)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 55 }] + }, + { + code: "if (a || b || c) {} else if (a || (b && d) || (c && e)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 30 }] + }, + { + code: "if (a || (b || c)) {} else if (a || (b && c)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 32 }] + }, + { + code: "if (a || b) {} else if (c) {} else if (d) {} else if ((a || c) && (b || d)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 55 }] + }, + { + code: "if (a) {} else if (b) {} else if (c && (a || d && b)) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 35 }] + }, + { + code: "if (a) {} else if (a || a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 20 }] + }, + { + code: "if (a || a) {} else if (a || a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a || a) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 25 }] + }, + { + code: "if (a) {} else if (a && a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 20 }] + }, + { + code: "if (a && a) {} else if (a && a) {}", + errors: [{ messageId: "unexpected", type: "LogicalExpression", column: 25 }] + }, + { + code: "if (a && a) {} else if (a) {}", + errors: [{ messageId: "unexpected", type: "Identifier", column: 25 }] } ] }); From d9f0d667564d33c012c41c4b709d98745cbdaa59 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Wed, 13 Nov 2019 01:13:56 +0100 Subject: [PATCH 3/4] Rename variables --- lib/rules/no-dupe-else-if.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rules/no-dupe-else-if.js b/lib/rules/no-dupe-else-if.js index 9106fe466a1..bf19b733cf6 100644 --- a/lib/rules/no-dupe-else-if.js +++ b/lib/rules/no-dupe-else-if.js @@ -105,13 +105,13 @@ module.exports = { while (current.parent && current.parent.type === "IfStatement" && current.parent.alternate === current) { current = current.parent; - const currentConditions = splitByOr(current.test).map(splitByAnd); + const currentOrOperands = splitByOr(current.test).map(splitByAnd); - listToCheck = listToCheck.map(e => e.filter( - lc => !currentConditions.some(cc => isSubset(cc, lc)) + listToCheck = listToCheck.map(orOperands => orOperands.filter( + orOperand => !currentOrOperands.some(currentOrOperand => isSubset(currentOrOperand, orOperand)) )); - if (listToCheck.some(e => e.length === 0)) { + if (listToCheck.some(orOperands => orOperands.length === 0)) { context.report({ node: test, messageId: "unexpected" }); break; } From ec49da1263ec012c7783b33b28ba11f66c6acb76 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Mon, 18 Nov 2019 17:42:41 +0100 Subject: [PATCH 4/4] Update lib/rules/no-dupe-else-if.js Co-Authored-By: Kai Cataldo --- lib/rules/no-dupe-else-if.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/no-dupe-else-if.js b/lib/rules/no-dupe-else-if.js index bf19b733cf6..a165e16607d 100644 --- a/lib/rules/no-dupe-else-if.js +++ b/lib/rules/no-dupe-else-if.js @@ -60,7 +60,7 @@ module.exports = { schema: [], messages: { - unexpected: "This branch can never execute, its condition is a duplicate or covered by previous conditions in the if-else-if chain." + unexpected: "This branch can never execute. Its condition is a duplicate or covered by previous conditions in the if-else-if chain." } },