Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix: prefer-numeric-literals doesn't check types of literal arguments (
  • Loading branch information
mdjermanovic authored and btmills committed Dec 20, 2019
1 parent e3c570e commit 45364af
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 29 deletions.
57 changes: 29 additions & 28 deletions lib/rules/prefer-numeric-literals.js
Expand Up @@ -15,6 +15,12 @@ const astUtils = require("./utils/ast-utils");
// Helpers
//------------------------------------------------------------------------------

const radixMap = new Map([
[2, { system: "binary", literalPrefix: "0b" }],
[8, { system: "octal", literalPrefix: "0o" }],
[16, { system: "hexadecimal", literalPrefix: "0x" }]
]);

/**
* Checks to see if a CallExpression's callee node is `parseInt` or
* `Number.parseInt`.
Expand Down Expand Up @@ -54,59 +60,54 @@ module.exports = {
},

schema: [],

messages: {
useLiteral: "Use {{system}} literals instead of {{functionName}}()."
},

fixable: "code"
},

create(context) {
const sourceCode = context.getSourceCode();

const radixMap = {
2: "binary",
8: "octal",
16: "hexadecimal"
};

const prefixMap = {
2: "0b",
8: "0o",
16: "0x"
};

//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------

return {

CallExpression(node) {

// doesn't check parseInt() if it doesn't have a radix argument
if (node.arguments.length !== 2) {
return;
}
"CallExpression[arguments.length=2]"(node) {
const [strNode, radixNode] = node.arguments,
str = strNode.value,
radix = radixNode.value;

if (
strNode.type === "Literal" &&
radixNode.type === "Literal" &&
typeof str === "string" &&
typeof radix === "number" &&
radixMap.has(radix) &&
isParseInt(node.callee)
) {

// only error if the radix is 2, 8, or 16
const radixName = radixMap[node.arguments[1].value];
const { system, literalPrefix } = radixMap.get(radix);

if (isParseInt(node.callee) &&
radixName &&
node.arguments[0].type === "Literal"
) {
context.report({
node,
message: "Use {{radixName}} literals instead of {{functionName}}().",
messageId: "useLiteral",
data: {
radixName,
system,
functionName: sourceCode.getText(node.callee)
},
fix(fixer) {
if (sourceCode.getCommentsInside(node).length) {
return null;
}

const replacement = `${prefixMap[node.arguments[1].value]}${node.arguments[0].value}`;
const replacement = `${literalPrefix}${str}`;

if (+replacement !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
if (+replacement !== parseInt(str, radix)) {

/*
* If the newly-produced literal would be invalid, (e.g. 0b1234),
Expand Down
23 changes: 22 additions & 1 deletion tests/lib/rules/prefer-numeric-literals.js
Expand Up @@ -31,7 +31,28 @@ ruleTester.run("prefer-numeric-literals", rule, {
"parseInt(foo);",
"parseInt(foo, 2);",
"Number.parseInt(foo);",
"Number.parseInt(foo, 2);"
"Number.parseInt(foo, 2);",
"parseInt(11, 2);",
"Number.parseInt(1, 8);",
"parseInt(1e5, 16);",
"parseInt('11', '2');",
"Number.parseInt('11', '8');",
{
code: "parseInt('11', 2n);",
parserOptions: { ecmaVersion: 2020 }
},
{
code: "Number.parseInt('11', 8n);",
parserOptions: { ecmaVersion: 2020 }
},
{
code: "parseInt('11', 16n);",
parserOptions: { ecmaVersion: 2020 }
},
{
code: "parseInt(1n, 2);",
parserOptions: { ecmaVersion: 2020 }
}
],
invalid: [
{
Expand Down

0 comments on commit 45364af

Please sign in to comment.