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

New: prefer-numeric-literals rule (fixes #6068) #7029

Merged
merged 1 commit into from
Sep 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf/eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
"padded-blocks": "off",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-numeric-literals": "off",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
Expand Down
49 changes: 49 additions & 0 deletions docs/rules/prefer-numeric-literals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# disallow `parseInt()` in favor of binary, octal, and hexadecimal literals (prefer-numeric-literals)

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()`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe rule encourages the use


```js
0b111110111 === 503;
0o767 === 503;
```

## Rule Details

This rule disallows `parseInt()` if it is called with two arguments: a string and a radix option of 2 (binary), 8 (octal), or 16 (hexadecimal).

Examples of **incorrect** code for this rule:

```js
/*eslint prefer-numeric-literals: "error"*/

parseInt("111110111", 2) === 503;
parseInt("767", 8) === 503;
parseInt("1F7", 16) === 255;
```

Examples of **correct** code for this rule:

```js
/*eslint prefer-numeric-literals: "error"*/
/*eslint-env es6*/

parseInt(1);
parseInt(1, 3);

0b111110111 === 503;
0o767 === 503;
0x1F7 === 503;

a[parseInt](1,2);

parseInt(foo);
parseInt(foo, 2);
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a JSCS compatibility section and a "When not to use it" section? See https://github.com/eslint/eslint/blob/master/docs/rules/no-tabs.md as an example.

Copy link
Contributor Author

@annie annie Sep 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nzakas sure thing! what should i put in the "when not to use it" section? not too familiar with the cases where you would want to use parseInt() vs. numeric literals

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a style thing so if you'd rather have a literal than parseInt you would use it, or if you don't use es6

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if you don't use ES6 then you definitely shouldn't use it. Or, if you are ok with usingbparseInt in this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in the Stylistic Issues rule category instead of ES6 then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past, the fact that rules are related to ES6-specific features seems to trump the fact that they are stylistic rules. I'm personally fine with leaving it in the ES6 category.


## When Not To Use It

If you want to allow use of `parseInt()` for binary, octal, or hexadecimal integers. If you are not using ES6 (because binary and octal literals are not supported in ES5 and below).

## Compatibility

* **JSCS**: [requireNumericLiterals](http://jscs.info/rule/requireNumericLiterals)
62 changes: 62 additions & 0 deletions lib/rules/prefer-numeric-literals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* @fileoverview Rule to disallow `parseInt()` in favor of binary, octal, and hexadecimal literals
* @author Annie Zhang, Henry Zhu
*/

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: "disallow `parseInt()` in favor of binary, octal, and hexadecimal literals",
category: "ECMAScript 6",
recommended: false
},

schema: []
},

create(context) {
const radixMap = {
2: "binary",
8: "octal",
16: "hexadecimal"
};

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

return {

CallExpression(node) {

// doesn't check parseInt() if it doesn't have a radix argument
if (node.arguments.length !== 2) {
return;
}

// only error if the radix is 2, 8, or 16
const radixName = radixMap[node.arguments[1].value];

if (node.callee.type === "Identifier" &&
node.callee.name === "parseInt" &&
radixName &&
node.arguments[0].type === "Literal"
) {
context.report({
node,
message: "Use {{radixName}} literals instead of parseInt().",
data: {
radixName
}
});
}
}
};
}
};
47 changes: 47 additions & 0 deletions tests/lib/rules/prefer-numeric-literals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @fileoverview Tests for prefer-numeric-literals rule.
* @author Annie Zhang
*/

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/prefer-numeric-literals"),
RuleTester = require("../../../lib/testers/rule-tester");

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester();

ruleTester.run("prefer-numeric-literals", rule, {
valid: [
"parseInt(1);",
"parseInt(1, 3);",
{ code: "0b111110111 === 503;", parserOptions: { ecmaVersion: 6 } },
{ code: "0o767 === 503;", parserOptions: { ecmaVersion: 6 } },
"0x1F7 === 503;",
"a[parseInt](1,2);",
"parseInt(foo);",
"parseInt(foo, 2);"
],
invalid: [
{
code: "parseInt(\"111110111\", 2) === 503;",
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Use binary literals instead of parseInt()." }]
}, {
code: "parseInt(\"767\", 8) === 503;",
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Use octal literals instead of parseInt()." }]
}, {
code: "parseInt(\"1F7\", 16) === 255;",
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Use hexadecimal literals instead of parseInt()." }]
}
]
});