Skip to content

Commit

Permalink
prefer-number-is-integer: update rule implementation from review
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanHessell committed Jan 27, 2022
1 parent 43ef6dc commit 6b4f721
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 21 deletions.
2 changes: 1 addition & 1 deletion configs/recommended.js
Expand Up @@ -77,8 +77,8 @@ module.exports = {
'unicorn/prefer-module': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-node-protocol': 'error',
'unicorn/prefer-number-properties': 'error',
'unicorn/prefer-number-is-integer': 'error',
'unicorn/prefer-number-properties': 'error',
'unicorn/prefer-object-from-entries': 'error',
'unicorn/prefer-optional-catch-binding': 'error',
'unicorn/prefer-prototype-methods': 'error',
Expand Down
7 changes: 7 additions & 0 deletions docs/rules/prefer-number-is-integer.md
@@ -1,5 +1,12 @@
# Prefer `Number.isInteger()` for integer checking

<!-- Do not manually modify RULE_NOTICE part. Run: `npm run generate-rule-notices` -->
<!-- RULE_NOTICE -->
*This rule is part of the [recommended](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config) config.*

💡 *This rule provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).*
<!-- /RULE_NOTICE -->

Enforces the use of [Number.isInteger()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger) for checking if a number is an integer.

There are multiple ways to check if a variable is an integer, but these approaches tend to have slightly different behaviours.
Expand Down
34 changes: 17 additions & 17 deletions rules/prefer-number-is-integer.js
@@ -1,5 +1,6 @@
'use strict';

const {methodCallSelector} = require('./selectors/index.js');
const isSameReference = require('./utils/is-same-reference.js');

const MESSAGE_ID = 'preferNumberIsInteger';
Expand All @@ -11,7 +12,7 @@ const messages = {

const equalsSelector = ':matches([operator="==="],[operator="=="])';

// Value % 1 === 0
// `value % 1 === 0`
const modulo1Selector = [
'BinaryExpression',
'[left.type="BinaryExpression"]',
Expand All @@ -21,7 +22,8 @@ const modulo1Selector = [
'[right.value="0"]',
].join('');

// (value^0) === value OR (value | 0) === value
// `(value ^ 0) === value`
// `(value | 0) === value`
const mathOperatorSelector = [
'BinaryExpression',
'[left.type="BinaryExpression"]',
Expand All @@ -30,33 +32,30 @@ const mathOperatorSelector = [
equalsSelector,
].join('');

// ParseInt(value,10) === value
const parseIntSelector = [
// `Number.parseInt(value,10) === value`
const numberParseIntSelector = [
'BinaryExpression',
'[left.type="CallExpression"]',
'[left.callee.name="parseInt"]',
'[left.callee.type="MemberExpression"]',
'[left.callee.object.name="Number"]',
'[left.callee.property.name="parseInt"]',
'[left.arguments.1.value=10]',
equalsSelector,
].join('');

// _.isInteger(value)
// `_.isInteger(value)`
const lodashIsIntegerSelector = [
'CallExpression',
`:matches(${['_', 'lodash', 'underscore'].map(callee => `[callee.object.name="${callee}"]`).join(',')})`,
'[callee.property.name="isInteger"]',
methodCallSelector({method: 'isInteger', objects: ['_', 'lodash', 'underscore']}),
].join('');

// Math.round(value) === value
// `Math.round(value) === value`
const mathRoundSelector = [
'BinaryExpression',
'[left.type="CallExpression"]',
'[left.callee.type="MemberExpression"]',
'[left.callee.object.name="Math"]',
'[left.callee.property.name="round"]',
methodCallSelector({method: 'round', object: 'Math', path: 'left'}),
equalsSelector,
].join('');

// ~~value === value
// `~~value === value`
const bitwiseNotSelector = [
'BinaryExpression',
'[left.type="UnaryExpression"]',
Expand Down Expand Up @@ -121,7 +120,7 @@ const create = context => {
return getNodeName(node.right);
}
}),
[parseIntSelector]: createNodeListener(sourceCode, node => {
[numberParseIntSelector]: createNodeListener(sourceCode, node => {
if (
isSameReference(node.left.arguments[0], node.right)
) {
Expand All @@ -144,14 +143,15 @@ const create = context => {
};
};

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
description: 'Prefer `Number.isInteger()` for integer checking.',
},
messages,
hasSuggestions: true,
messages,
},
};
6 changes: 3 additions & 3 deletions test/prefer-number-is-integer.mjs
Expand Up @@ -20,7 +20,7 @@ test({
'(value^0) === notValue',
'(value | 0) === notValue',
'Math.round(value) === notValue',
'parseInt(value, 10) === notValue',
'Number.parseInt(value, 10) === notValue',
'~~value === notValue',
],
invalid: [
Expand Down Expand Up @@ -48,11 +48,11 @@ test({
messageId: 'preferNumberIsIntegerSuggestion',
output: 'Number.isInteger(value)',
}]}),
suggestionCase({code: 'parseInt(value, 10) === value', suggestions: [{
suggestionCase({code: 'Number.parseInt(value, 10) === value', suggestions: [{
messageId: 'preferNumberIsIntegerSuggestion',
output: 'Number.isInteger(value)',
}]}),
suggestionCase({code: 'parseInt(value, 10) == value', suggestions: [{
suggestionCase({code: 'Number.parseInt(value, 10) == value', suggestions: [{
messageId: 'preferNumberIsIntegerSuggestion',
output: 'Number.isInteger(value)',
}]}),
Expand Down

0 comments on commit 6b4f721

Please sign in to comment.