Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: yoda left string fix for exceptRange (fixes #12883) #13052

Merged
merged 13 commits into from Apr 24, 2020
Merged
44 changes: 34 additions & 10 deletions lib/rules/yoda.js
Expand Up @@ -245,11 +245,23 @@ module.exports = {
function isBetweenTest() {
let leftLiteral, rightLiteral;

return (node.operator === "&&" &&
(leftLiteral = getNormalizedLiteral(left.left)) &&
(rightLiteral = getNormalizedLiteral(right.right, Number.POSITIVE_INFINITY)) &&
leftLiteral.value <= rightLiteral.value &&
same(left.right, right.left));
if (node.operator === "&&") {
leftLiteral = getNormalizedLiteral(left.left);
rightLiteral = getNormalizedLiteral(right.right, Number.POSITIVE_INFINITY);

if (leftLiteral && rightLiteral) {

if (leftLiteral.value <= rightLiteral.value && same(left.right, right.left)) {
return true;
}

if ((typeof leftLiteral.value === "string" && typeof rightLiteral.value !== "string") ||
(typeof rightLiteral.value === "string" && typeof leftLiteral.value !== "string")) {
return true;
}
}
}
return false;
}

/**
Expand All @@ -259,11 +271,23 @@ module.exports = {
function isOutsideTest() {
let leftLiteral, rightLiteral;

return (node.operator === "||" &&
(leftLiteral = getNormalizedLiteral(left.right, Number.NEGATIVE_INFINITY)) &&
(rightLiteral = getNormalizedLiteral(right.left)) &&
leftLiteral.value <= rightLiteral.value &&
same(left.left, right.right));
if (node.operator === "||") {
leftLiteral = getNormalizedLiteral(left.right, Number.POSITIVE_INFINITY);
rightLiteral = getNormalizedLiteral(right.left);

if (leftLiteral && rightLiteral) {
if ((rightLiteral.value <= leftLiteral.value) && same(left.left, right.right)) {
return true;
}

if ((typeof leftLiteral.value === "string" && typeof rightLiteral.value !== "string") ||
(typeof rightLiteral.value === "string" && typeof leftLiteral.value !== "string")) {
return true;
}
}
}

return false;
}

/**
Expand Down
195 changes: 162 additions & 33 deletions tests/lib/rules/yoda.js
Expand Up @@ -50,17 +50,28 @@ ruleTester.run("yoda", rule, {

// Range exception
{
code: "if (0 < x && x <= 1) {}",
code: "if (\"a\" < x && x < MAX ) {}",
options: ["never", { exceptRange: true }]
}, {
code: "if (x < 0 || 1 <= x) {}",
},
{
code: "if (1 < x && x < MAX ) {}",
options: ["never", { exceptRange: true }]
},
{
code: "if ('a' < x && x < MAX ) {}",
options: ["never", { exceptRange: true }]
},
{
code: "if (x < `x` || `x` <= x) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
},
{
code: "if (0 < x && x <= 1) {}",
options: ["never", { exceptRange: true }]
}, {
code: "if (0 <= x && x < 1) {}",
options: ["always", { exceptRange: true }]
}, {
code: "if (x <= 'bar' || 'foo' < x) {}",
options: ["always", { exceptRange: true }]
}, {
code: "if ('blue' < x.y && x.y < 'green') {}",
options: ["never", { exceptRange: true }]
Expand All @@ -81,9 +92,6 @@ ruleTester.run("yoda", rule, {
}, {
code: "if ((0 < a && a < 1) && b < 0) {}",
options: ["never", { exceptRange: true }]
}, {
code: "if (a < 4 || (b[c[0]].d['e'] < 0 || 1 <= b[c[0]].d['e'])) {}",
options: ["never", { exceptRange: true }]
}, {
code: "if (-1 < x && x < 0) {}",
options: ["never", { exceptRange: true }]
Expand Down Expand Up @@ -113,18 +121,10 @@ ruleTester.run("yoda", rule, {
code: "if (-1n < x && x <= 1n) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 }
}, {
code: "if (x < -1n || 1n <= x) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 }
}, {
code: "if (-1n <= x && x < 1n) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 }
}, {
code: "if (x < -1n || 1n <= x) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 }
}, {
code: "if (x < `1` || `1` < x) {}",
options: ["always", { exceptRange: true }],
Expand All @@ -134,23 +134,50 @@ ruleTester.run("yoda", rule, {
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2018 }
}, {
code: "if (x <= `bar` || `foo` < x) {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
code: "if ('a' < x && x < MAX ) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if (`blue` < x.y && x.y < `green`) {}",
code: "if ('a' < x && x < MAX ) {}",
options: ["always"],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if (x <= 'foo' || 'bar' < x) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if (MIN < x && x < 'a' ) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if (MIN < x && x < 'a' ) {}",
options: ["never"],
parserOptions: { ecmaVersion: 2015 }
},
{
code: "if (`blue` < x.y && x.y < `green`) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
},
{
code: "if ('a' < x && x < MAX ) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
},
{
code: "if (0 <= x[`y`] && x[`y`] <= 100) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if (0 <= x[`y`] && x[\"y\"] <= 100) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 }
}, {
code: "if ('a' <= x && x < 'b') {}",
options: ["never", { exceptRange: true }]
},


// onlyEquality
{ code: "if (0 < x && x <= 1) {}", options: ["never", { onlyEquality: true }] },
{ code: "if (x !== 'foo' && 'foo' !== x) {}", options: ["never", { onlyEquality: true }] },
Expand All @@ -159,7 +186,18 @@ ruleTester.run("yoda", rule, {
{ code: "if (x < `2` && x !== `-3`) {}", options: ["always", { onlyEquality: true }], parserOptions: { ecmaVersion: 2015 } }
],
invalid: [

{
code: "if (x <= 'bar' || 'foo' < x) {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if ('bar' >= x || 'foo' < x) {}",
options: ["always", { exceptRange: true }],
errors: [
{
messageId: "expected",
data: { expectedSide: "left", operator: "<=" },
type: "BinaryExpression"
}
]
},
{
code: "if (\"red\" == value) {}",
output: "if (value == \"red\") {}",
Expand Down Expand Up @@ -641,19 +679,6 @@ ruleTester.run("yoda", rule, {
}
]
},
{
code: "if (`green` < x.y && x.y < `blue`) {}",
output: "if (x.y > `green` && x.y < `blue`) {}",
options: ["never", { exceptRange: true }],
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
parserOptions: { ecmaVersion: 2015 },
errors: [
{
messageId: "expected",
data: { expectedSide: "right", operator: "<" },
type: "BinaryExpression"
}
]
},
{
code: "if (3 == a) {}",
output: "if (a == 3) {}",
Expand Down Expand Up @@ -992,6 +1017,110 @@ ruleTester.run("yoda", rule, {
type: "BinaryExpression"
}
]
},
{
code: "if (`green` < x.y && x.y < `blue`) {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if (`green` < x.y && `blue` > x.y) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2015 },
errors: [
{
messageId: "expected",
data: { expectedSide: "left", operator: "<" },
type: "BinaryExpression"
}
]
},
{
code: "if (x < -1n || 1n <= x) {}",
output: "if (x < -1n || x >= 1n) {}",
options: ["never", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 },
errors: [
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
{
messageId: "expected",
data: { expectedSide: "right", operator: "<=" },
type: "BinaryExpression"
}
]
},
{
code: "if('a' <= x && x < 'b') {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if('a' <= x && 'b' > x) {}",
options: ["always"],
errors: [
{
messageId: "expected",
data: { expectedSide: "left", operator: "<" },
type: "BinaryExpression"
}
]
},
{
code: "if (x < -1n || 1n <= x) {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if (-1n > x || 1n <= x) {}",
options: ["always", { exceptRange: true }],
parserOptions: { ecmaVersion: 2020 },
errors: [
{
messageId: "expected",
data: { expectedSide: "left", operator: "<" },
type: "BinaryExpression"
}
]
},
{
code: "if (x < 0 || 1 <= x) {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if (x < 0 || x >= 1) {}",
options: ["never", { exceptRange: true }],
errors: [
{
messageId: "expected",
data: { expectedSide: "right", operator: "<=" },
type: "BinaryExpression"
}
]
},
{
code: "if ('b' <= x && x < 'a') {}",
anikethsaha marked this conversation as resolved.
Show resolved Hide resolved
output: "if (x >= 'b' && x < 'a') {}",
options: ["never", { exceptRange: true }],
errors: [
{
messageId: "expected",
data: { expectedSide: "right", operator: "<=" },
type: "BinaryExpression"
}
]
},
{
code: "if (a < 4 || (b[c[0]].d['e'] < 0 || 1 <= b[c[0]].d['e'])) {}",
output: "if (a < 4 || (b[c[0]].d['e'] < 0 || b[c[0]].d['e'] >= 1)) {}",
options: ["never", { exceptRange: true }],
errors: [
{
messageId: "expected",
data: { expectedSide: "right", operator: "<=" },
type: "BinaryExpression"
}
]
},
{
code: "if (a < 4 || (b[c[0]].d['e'] < 0 || 1 <= b[c[0]].d['e'])) {}",
output: "if (4 > a || (0 > b[c[0]].d['e'] || 1 <= b[c[0]].d['e'])) {}",
options: ["always", { exceptRange: true }],
errors: [
{
messageId: "expected",
data: { expectedSide: "left", operator: "<" },
type: "BinaryExpression"
},
{
messageId: "expected",
data: { expectedSide: "left", operator: "<" },
type: "BinaryExpression"
}
]
}
]
});