mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.4 KiB
131 lines
4.4 KiB
9 years ago
|
/**
|
||
|
* @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js)
|
||
|
* @author Vincent Lemeunier
|
||
|
* @copyright 2015 Vincent Lemeunier. All rights reserved.
|
||
|
*
|
||
|
* This rule was adapted from danielstjules/buddy.js
|
||
|
* The MIT License (MIT)
|
||
|
*
|
||
|
* Copyright (c) 2014 Daniel St. Jules
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
|
||
|
* The above copyright notice and this permission notice shall be included in all
|
||
|
* copies or substantial portions of the Software.
|
||
|
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*
|
||
|
* See LICENSE file in root directory for full license.
|
||
|
*/
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Rule Definition
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
module.exports = function(context) {
|
||
|
var config = context.options[0] || {},
|
||
|
ignore = config.ignore || [0, 1, 2],
|
||
|
detectObjects = !!config.detectObjects,
|
||
|
enforceConst = !!config.enforceConst;
|
||
|
|
||
|
/**
|
||
|
* Returns whether the node is number literal
|
||
|
* @param {Node} node - the node literal being evaluated
|
||
|
* @returns {boolean} true if the node is a number literal
|
||
|
*/
|
||
|
function isNumber(node) {
|
||
|
return typeof node.value === "number";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the number should be ignored
|
||
|
* @param {number} num - the number
|
||
|
* @returns {boolean} true if the number should be ignored
|
||
|
*/
|
||
|
function shouldIgnoreNumber(num) {
|
||
|
return ignore.indexOf(num) !== -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
return {
|
||
|
"Literal": function(node) {
|
||
|
var parent = node.parent,
|
||
|
value = node.value,
|
||
|
raw = node.raw,
|
||
|
okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
|
||
|
|
||
|
if (!isNumber(node)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (parent.type === "UnaryExpression" && parent.operator === "-") {
|
||
|
node = parent;
|
||
|
parent = node.parent;
|
||
|
value = -value;
|
||
|
raw = "-" + raw;
|
||
|
}
|
||
|
|
||
|
if (shouldIgnoreNumber(value)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// don't warn on parseInt() or Number.parseInt() radix
|
||
|
if (parent.type === "CallExpression" && node === parent.arguments[1] &&
|
||
|
(parent.callee.name === "parseInt" ||
|
||
|
parent.callee.type === "MemberExpression" &&
|
||
|
parent.callee.object.name === "Number" &&
|
||
|
parent.callee.property.name === "parseInt")
|
||
|
) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (parent.type === "VariableDeclarator") {
|
||
|
if (enforceConst && parent.parent.kind !== "const") {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: "Number constants declarations must use 'const'"
|
||
|
});
|
||
|
}
|
||
|
} else if (okTypes.indexOf(parent.type) === -1) {
|
||
|
context.report({
|
||
|
node: node,
|
||
|
message: "No magic number: " + raw
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
module.exports.schema = [{
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"detectObjects": {
|
||
|
"type": "boolean"
|
||
|
},
|
||
|
"enforceConst": {
|
||
|
"type": "boolean"
|
||
|
},
|
||
|
"ignore": {
|
||
|
"type": "array",
|
||
|
"items": {
|
||
|
"type": "number"
|
||
|
},
|
||
|
"uniqueItems": true
|
||
|
}
|
||
|
},
|
||
|
"additionalProperties": false
|
||
|
}];
|