Skip to content

Commit 0b21e1f

Browse files
gurgundayfasttime
andauthored
feat!: add two more cases to no-implicit-coercion (#17832)
* add two more cases * fix comment * docs * add allow * change operator * change docs * use - - * add tests * don't fix numbers * Check type directly Co-authored-by: Francesco Trotta <[email protected]> * add examples * Refactor implicit coercion check in no-implicit-coercion rule * fix test * fix test * Revert "Refactor implicit coercion check in no-implicit-coercion rule" * make non-fixable * Revert "fix test" * add back test --------- Co-authored-by: Francesco Trotta <[email protected]>
1 parent e6a91bd commit 0b21e1f

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

docs/src/rules/no-implicit-coercion.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Such as:
1414
var b = !!foo;
1515
var b = ~foo.indexOf(".");
1616
var n = +foo;
17+
var n = -(-foo);
18+
var n = foo - 0;
1719
var n = 1 * foo;
1820
var s = "" + foo;
1921
foo += ``;
@@ -26,6 +28,8 @@ var b = Boolean(foo);
2628
var b = foo.indexOf(".") !== -1;
2729
var n = Number(foo);
2830
var n = Number(foo);
31+
var n = Number(foo);
32+
var n = Number(foo);
2933
var s = String(foo);
3034
foo = String(foo);
3135
```
@@ -42,7 +46,7 @@ This rule has three main options and one override option to allow some coercions
4246
* `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
4347
* `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
4448
* `"disallowTemplateShorthand"` (`false` by default) - When this is `true`, this rule warns `string` type conversions using `${expression}` form.
45-
* `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
49+
* `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+`, `- -`, `-`, or `*` that are to be allowed.
4650

4751
Note that operator `+` in `allow` list would allow `+foo` (number coercion) as well as `"" + foo` (string coercion).
4852

@@ -87,6 +91,8 @@ Examples of **incorrect** code for the default `{ "number": true }` option:
8791
/*eslint no-implicit-coercion: "error"*/
8892

8993
var n = +foo;
94+
var n = -(-foo);
95+
var n = foo - 0;
9096
var n = 1 * foo;
9197
```
9298

lib/rules/no-implicit-coercion.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const astUtils = require("./utils/ast-utils");
1212
//------------------------------------------------------------------------------
1313

1414
const INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/u;
15-
const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"];
15+
const ALLOWABLE_OPERATORS = ["~", "!!", "+", "- -", "-", "*"];
1616

1717
/**
1818
* Parses and normalizes an option object.
@@ -300,6 +300,14 @@ module.exports = {
300300

301301
report(node, recommendation, true);
302302
}
303+
304+
// -(-foo)
305+
operatorAllowed = options.allow.includes("- -");
306+
if (!operatorAllowed && options.number && node.operator === "-" && node.argument.type === "UnaryExpression" && node.argument.operator === "-" && !isNumeric(node.argument.argument)) {
307+
const recommendation = `Number(${sourceCode.getText(node.argument.argument)})`;
308+
309+
report(node, recommendation, false);
310+
}
303311
},
304312

305313
// Use `:exit` to prevent double reporting
@@ -317,6 +325,14 @@ module.exports = {
317325
report(node, recommendation, true);
318326
}
319327

328+
// foo - 0
329+
operatorAllowed = options.allow.includes("-");
330+
if (!operatorAllowed && options.number && node.operator === "-" && node.right.type === "Literal" && node.right.value === 0 && !isNumeric(node.left)) {
331+
const recommendation = `Number(${sourceCode.getText(node.left)})`;
332+
333+
report(node, recommendation, true);
334+
}
335+
320336
// "" + foo
321337
operatorAllowed = options.allow.includes("+");
322338
if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) {

tests/lib/rules/no-implicit-coercion.js

+28
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,23 @@ ruleTester.run("no-implicit-coercion", rule, {
3131
"-foo",
3232
"+1234",
3333
"-1234",
34+
"- -1234",
3435
"+Number(lol)",
3536
"-parseFloat(lol)",
3637
"2 * foo",
3738
"1 * 1234",
39+
"123 - 0",
3840
"1 * Number(foo)",
3941
"1 * parseInt(foo)",
4042
"1 * parseFloat(foo)",
4143
"Number(foo) * 1",
44+
"Number(foo) - 0",
4245
"parseInt(foo) * 1",
4346
"parseFloat(foo) * 1",
47+
"- -Number(foo)",
4448
"1 * 1234 * 678 * Number(foo)",
4549
"1 * 1234 * 678 * parseInt(foo)",
50+
"(1 - 0) * parseInt(foo)",
4651
"1234 * 1 * 678 * Number(foo)",
4752
"1234 * 1 * Number(foo) * Number(bar)",
4853
"1234 * 1 * Number(foo) * parseInt(bar)",
@@ -54,6 +59,7 @@ ruleTester.run("no-implicit-coercion", rule, {
5459
"1234 * parseInt(foo) * 1 * Number(bar)",
5560
"1234 * parseFloat(foo) * 1 * parseInt(bar)",
5661
"1234 * parseFloat(foo) * 1 * Number(bar)",
62+
"(- -1234) * (parseFloat(foo) - 0) * (Number(bar) - 0)",
5763
"1234*foo*1",
5864
"1234*1*foo",
5965
"1234*bar*1*foo",
@@ -69,13 +75,17 @@ ruleTester.run("no-implicit-coercion", rule, {
6975
{ code: "!!foo", options: [{ boolean: false }] },
7076
{ code: "~foo.indexOf(1)", options: [{ boolean: false }] },
7177
{ code: "+foo", options: [{ number: false }] },
78+
{ code: "-(-foo)", options: [{ number: false }] },
79+
{ code: "foo - 0", options: [{ number: false }] },
7280
{ code: "1*foo", options: [{ number: false }] },
7381
{ code: "\"\"+foo", options: [{ string: false }] },
7482
{ code: "foo += \"\"", options: [{ string: false }] },
7583
{ code: "var a = !!foo", options: [{ boolean: true, allow: ["!!"] }] },
7684
{ code: "var a = ~foo.indexOf(1)", options: [{ boolean: true, allow: ["~"] }] },
7785
{ code: "var a = ~foo", options: [{ boolean: true }] },
7886
{ code: "var a = 1 * foo", options: [{ boolean: true, allow: ["*"] }] },
87+
{ code: "- -foo", options: [{ number: true, allow: ["- -"] }] },
88+
{ code: "foo - 0", options: [{ number: true, allow: ["-"] }] },
7989
{ code: "var a = +foo", options: [{ boolean: true, allow: ["+"] }] },
8090
{ code: "var a = \"\" + foo", options: [{ boolean: true, string: true, allow: ["+"] }] },
8191

@@ -157,6 +167,15 @@ ruleTester.run("no-implicit-coercion", rule, {
157167
type: "UnaryExpression"
158168
}]
159169
},
170+
{
171+
code: "-(-foo)",
172+
output: null,
173+
errors: [{
174+
messageId: "useRecommendation",
175+
data: { recommendation: "Number(foo)" },
176+
type: "UnaryExpression"
177+
}]
178+
},
160179
{
161180
code: "+foo.bar",
162181
output: "Number(foo.bar)",
@@ -193,6 +212,15 @@ ruleTester.run("no-implicit-coercion", rule, {
193212
type: "BinaryExpression"
194213
}]
195214
},
215+
{
216+
code: "foo.bar-0",
217+
output: "Number(foo.bar)",
218+
errors: [{
219+
messageId: "useRecommendation",
220+
data: { recommendation: "Number(foo.bar)" },
221+
type: "BinaryExpression"
222+
}]
223+
},
196224
{
197225
code: "\"\"+foo",
198226
output: "String(foo)",

0 commit comments

Comments
 (0)