Skip to content

Commit c05a19c

Browse files
not-an-aardvarknzakas
authored andcommitted
Update: add fixer for prefer-numeric-literals (#7205)
1 parent 2f171f3 commit c05a19c

3 files changed

Lines changed: 45 additions & 1 deletion

File tree

docs/rules/prefer-numeric-literals.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# disallow `parseInt()` in favor of binary, octal, and hexadecimal literals (prefer-numeric-literals)
22

3+
(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.
4+
35
The `parseInt()` function can be used to turn binary, octal, and hexadecimal strings into integers. As binary, octal, and hexadecimal literals are supported in ES6, this rule encourages use of those numeric literals instead of `parseInt()`.
46

57
```js

lib/rules/prefer-numeric-literals.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ module.exports = {
1717
recommended: false
1818
},
1919

20-
schema: []
20+
schema: [],
21+
22+
fixable: "code"
2123
},
2224

2325
create(context) {
@@ -27,6 +29,12 @@ module.exports = {
2729
16: "hexadecimal"
2830
};
2931

32+
const prefixMap = {
33+
2: "0b",
34+
8: "0o",
35+
16: "0x"
36+
};
37+
3038
//--------------------------------------------------------------------------
3139
// Public
3240
//--------------------------------------------------------------------------
@@ -53,6 +61,17 @@ module.exports = {
5361
message: "Use {{radixName}} literals instead of parseInt().",
5462
data: {
5563
radixName
64+
},
65+
fix(fixer) {
66+
const newPrefix = prefixMap[node.arguments[1].value];
67+
68+
if (+(newPrefix + node.arguments[0].value) !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
69+
70+
// If the newly-produced literal would be invalid, (e.g. 0b1234),
71+
// or it would yield an incorrect parseInt result for some other reason, don't make a fix.
72+
return null;
73+
}
74+
return fixer.replaceText(node, prefixMap[node.arguments[1].value] + node.arguments[0].value);
5675
}
5776
});
5877
}

tests/lib/rules/prefer-numeric-literals.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,39 @@ ruleTester.run("prefer-numeric-literals", rule, {
3232
invalid: [
3333
{
3434
code: "parseInt(\"111110111\", 2) === 503;",
35+
output: "0b111110111 === 503;",
3536
parserOptions: { ecmaVersion: 6 },
3637
errors: [{ message: "Use binary literals instead of parseInt()." }]
3738
}, {
3839
code: "parseInt(\"767\", 8) === 503;",
40+
output: "0o767 === 503;",
3941
parserOptions: { ecmaVersion: 6 },
4042
errors: [{ message: "Use octal literals instead of parseInt()." }]
4143
}, {
4244
code: "parseInt(\"1F7\", 16) === 255;",
45+
output: "0x1F7 === 255;",
4346
parserOptions: { ecmaVersion: 6 },
4447
errors: [{ message: "Use hexadecimal literals instead of parseInt()." }]
48+
}, {
49+
code: "parseInt('7999', 8);",
50+
output: "parseInt('7999', 8);", // not fixed, unexpected 9 in parseInt string
51+
parserOptions: { ecmaVersion: 6 },
52+
errors: [{ message: "Use octal literals instead of parseInt()." }]
53+
}, {
54+
code: "parseInt('1234', 2);",
55+
output: "parseInt('1234', 2);", // not fixed, invalid binary string
56+
parserOptions: { ecmaVersion: 6 },
57+
errors: [{ message: "Use binary literals instead of parseInt()." }]
58+
}, {
59+
code: "parseInt('1234.5', 8);",
60+
output: "parseInt('1234.5', 8);", // not fixed, this isn't an integer
61+
parserOptions: { ecmaVersion: 6 },
62+
errors: [{ message: "Use octal literals instead of parseInt()." }]
63+
}, {
64+
code: "parseInt('1️⃣3️⃣3️⃣7️⃣', 16);",
65+
output: "parseInt('1️⃣3️⃣3️⃣7️⃣', 16);", // not fixed, javascript doesn't support emoji literals
66+
parserOptions: { ecmaVersion: 6 },
67+
errors: [{ message: "Use hexadecimal literals instead of parseInt()."}]
4568
}
4669
]
4770
});

0 commit comments

Comments
 (0)