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.

101 lines
3.8 KiB

/**
* @fileoverview Rule to suggest using "Reflect" api over Function/Object methods
* @author Keith Cirkel <http://keithcirkel.co.uk>
* @copyright 2015 Keith Cirkel. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var existingNames = {
"apply": "Function.prototype.apply",
"call": "Function.prototype.call",
"defineProperty": "Object.defineProperty",
"getOwnPropertyDescriptor": "Object.getOwnPropertyDescriptor",
"getPrototypeOf": "Object.getPrototypeOf",
"setPrototypeOf": "Object.setPrototypeOf",
"isExtensible": "Object.isExtensible",
"getOwnPropertyNames": "Object.getOwnPropertyNames",
"preventExtensions": "Object.preventExtensions"
};
var reflectSubsitutes = {
"apply": "Reflect.apply",
"call": "Reflect.apply",
"defineProperty": "Reflect.defineProperty",
"getOwnPropertyDescriptor": "Reflect.getOwnPropertyDescriptor",
"getPrototypeOf": "Reflect.getPrototypeOf",
"setPrototypeOf": "Reflect.setPrototypeOf",
"isExtensible": "Reflect.isExtensible",
"getOwnPropertyNames": "Reflect.getOwnPropertyNames",
"preventExtensions": "Reflect.preventExtensions"
};
var exceptions = (context.options[0] || {}).exceptions || [];
/**
* Reports the Reflect violation based on the `existing` and `substitute`
* @param {Object} node The node that violates the rule.
* @param {string} existing The existing method name that has been used.
* @param {string} substitute The Reflect substitute that should be used.
* @returns {void}
*/
function report(node, existing, substitute) {
context.report(node, "Avoid using {{existing}}, instead use {{substitute}}", {
existing: existing,
substitute: substitute
});
}
return {
"CallExpression": function(node) {
var methodName = (node.callee.property || {}).name;
var isReflectCall = (node.callee.object || {}).name === "Reflect";
var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName);
var userConfiguredException = exceptions.indexOf(methodName) !== -1;
if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
report(node, existingNames[methodName], reflectSubsitutes[methodName]);
}
},
"UnaryExpression": function(node) {
var isDeleteOperator = node.operator === "delete";
var targetsIdentifier = node.argument.type === "Identifier";
var userConfiguredException = exceptions.indexOf("delete") !== -1;
if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) {
report(node, "the delete keyword", "Reflect.deleteProperty");
}
}
};
};
module.exports.schema = [
{
"type": "object",
"properties": {
"exceptions": {
"type": "array",
"items": {
"enum": [
"apply",
"call",
"delete",
"defineProperty",
"getOwnPropertyDescriptor",
"getPrototypeOf",
"setPrototypeOf",
"isExtensible",
"getOwnPropertyNames",
"preventExtensions"
]
},
"uniqueItems": true
}
},
"additionalProperties": false
}
];