Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update: check logical assignment in no-constant-condition (#13946)
* Update: check logical assignment in no-constant-condition

* update docs
  • Loading branch information
mdjermanovic committed Jan 2, 2021
1 parent cc48713 commit e128e77
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 5 deletions.
8 changes: 8 additions & 0 deletions docs/rules/no-constant-condition.md
Expand Up @@ -28,6 +28,14 @@ if (void x) {
doSomethingUnfinished();
}

if (x &&= false) {
doSomethingNever();
}

if (x ||= true) {
doSomethingAlways();
}

for (;-2;) {
doSomethingForever();
}
Expand Down
19 changes: 16 additions & 3 deletions lib/rules/no-constant-condition.js
Expand Up @@ -106,10 +106,15 @@ module.exports = {
*/
return operator === node.operator &&
(
isLogicalIdentity(node.left, node.operator) ||
isLogicalIdentity(node.right, node.operator)
isLogicalIdentity(node.left, operator) ||
isLogicalIdentity(node.right, operator)
);

case "AssignmentExpression":
return ["||=", "&&="].includes(node.operator) &&
operator === node.operator.slice(0, -1) &&
isLogicalIdentity(node.right, operator);

// no default
}
return false;
Expand Down Expand Up @@ -177,7 +182,15 @@ module.exports = {
}

case "AssignmentExpression":
return (node.operator === "=") && isConstant(node.right, inBooleanPosition);
if (node.operator === "=") {
return isConstant(node.right, inBooleanPosition);
}

if (["||=", "&&="].includes(node.operator) && inBooleanPosition) {
return isLogicalIdentity(node.right, node.operator.slice(0, -1));
}

return false;

case "SequenceExpression":
return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
Expand Down
74 changes: 72 additions & 2 deletions tests/lib/rules/no-constant-condition.js
Expand Up @@ -16,13 +16,58 @@ const rule = require("../../../lib/rules/no-constant-condition"),
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2021 } });

ruleTester.run("no-constant-condition", rule, {
valid: [
"if(a);",
"if(a == 0);",
"if(a = f());",
"if(a += 1);",
"if(a |= 1);",
"if(a |= true);",
"if(a |= false);",
"if(a &= 1);",
"if(a &= true);",
"if(a &= false);",
"if(a >>= 1);",
"if(a >>= true);",
"if(a >>= false);",
"if(a >>>= 1);",
"if(a ??= 1);",
"if(a ??= true);",
"if(a ??= false);",
"if(a ||= b);",
"if(a ||= false);",
"if(a ||= 0);",
"if(a ||= void 0);",
"if(+(a ||= 1));",
"if(f(a ||= true));",
"if((a ||= 1) + 2);",
"if(1 + (a ||= true));",
"if(a ||= '' || false);",
"if(a ||= void 0 || null);",
"if((a ||= false) || b);",
"if(a || (b ||= false));",
"if((a ||= true) && b);",
"if(a && (b ||= true));",
"if(a &&= b);",
"if(a &&= true);",
"if(a &&= 1);",
"if(a &&= 'foo');",
"if((a &&= '') + false);",
"if('' + (a &&= null));",
"if(a &&= 1 && 2);",
"if((a &&= true) && b);",
"if(a && (b &&= true));",
"if((a &&= false) || b);",
"if(a || (b &&= false));",
"if(a ||= b ||= false);",
"if(a &&= b &&= true);",
"if(a ||= b &&= false);",
"if(a ||= b &&= true);",
"if(a &&= b ||= false);",
"if(a &&= b ||= true);",
"if(1, a);",
"if ('every' in []);",
"if (`\\\n${a}`) {}",
Expand Down Expand Up @@ -175,7 +220,32 @@ ruleTester.run("no-constant-condition", rule, {
{ code: "if(!typeof a === 'string');", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },
{ code: "if(-('foo' || a));", errors: [{ messageId: "unexpected", type: "UnaryExpression" }] },
{ code: "if(+(void a && b) === ~(1 || c));", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },

{ code: "if(a ||= true);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a ||= 5);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a ||= 'foo' || b);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a ||= b || /regex/);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a ||= b ||= true);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a ||= b ||= c || 1);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(!(a ||= true));", errors: [{ messageId: "unexpected", type: "UnaryExpression" }] },
{ code: "if(!(a ||= 'foo') === true);", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },
{ code: "if(!(a ||= 'foo') === false);", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },
{ code: "if(a || (b ||= true));", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if((a ||= 1) || b);", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if((a ||= true) && true);", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if(true && (a ||= true));", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if(a &&= false);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= null);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= void b);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= 0 && b);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= b && '');", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= b &&= false);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(a &&= b &&= c && false);", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
{ code: "if(!(a &&= false));", errors: [{ messageId: "unexpected", type: "UnaryExpression" }] },
{ code: "if(!(a &&= 0) + 1);", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },
{ code: "if(a && (b &&= false));", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if((a &&= null) && b);", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if(false || (a &&= false));", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if((a &&= false) || false);", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },

{ code: "while([]);", errors: [{ messageId: "unexpected", type: "ArrayExpression" }] },
{ code: "while(~!0);", errors: [{ messageId: "unexpected", type: "UnaryExpression" }] },
Expand Down

0 comments on commit e128e77

Please sign in to comment.