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.
 
 
 
 

88 lines
3.6 KiB

'use strict';
const kebabCase = require('kebab-case');
const rules = require('./rules');
const forbiddenLibs = ['lodash', 'lodash-es'];
function getAssignmentLeftHandSide(node) {
// For VariableDeclarator nodes, the left hand side is called `id`
// The `x` on `var x = 3;
if (node.type === 'VariableDeclarator') {
return node.id;
}
// For AssignmentExpression nodes, the left hand side is called `left`
// The `x` on `x = 3;
if (node.type === 'AssignmentExpression') {
return node.left;
}
return null;
}
for (const rule in rules) {
const alternative = rules[rule].alternative;
const ruleName = rules[rule].ruleName || kebabCase(rule);
const forbiddenImports = { [`lodash/${rule}`]: 1, [`lodash-es/${rule}`]: 1, [`lodash.${rule.toLowerCase()}`]: 1 };
module.exports[ruleName] = {
create(context) {
return {
CallExpression(node) {
const callee = node.callee;
const objectName = callee.name || (callee.object && callee.object.name) || (callee.object && callee.object.callee && callee.object.callee.name);
if (objectName === 'require' && node.arguments.length === 1) {
const requiredModuleName = node.arguments[0].value;
const { parent } = node;
if (forbiddenLibs.includes(requiredModuleName)) {
const leftHandSide = getAssignmentLeftHandSide(parent);
// ex: const { indexOf } = require('lodash');
// ex: ({ indexOf } = require('lodash'));
if (leftHandSide && leftHandSide.type === 'ObjectPattern') {
leftHandSide.properties.forEach(property => {
if (property.key.name === rule) {
context.report({
node,
message: `{ ${rule} } = require('${requiredModuleName}') detected. Consider using the native ${alternative}`
});
}
});
}
} else if (forbiddenImports.hasOwnProperty(requiredModuleName)) {
// ex: const indexOf = require('lodash.indexof');
// ex: const indexOf = require('lodash/indexOf');
context.report({
node,
message: `require('${requiredModuleName}') detected. Consider using the native ${alternative}`
});
}
} else if ((objectName === '_' || objectName === 'lodash' || objectName === 'underscore') && callee.property && callee.property.name === rule) {
context.report({
node,
message: `Consider using the native ${alternative}`
});
}
},
ImportDeclaration(node) {
if (forbiddenLibs.includes(node.source.value)) {
// ex: import { indexOf } from 'lodash';
// ex: import { indexOf as x } from 'lodash';
node.specifiers.forEach(specifier => {
if (specifier.type === 'ImportSpecifier' && specifier.imported.name === rule) {
context.report({
node,
message: `Import { ${rule} } from '${node.source.value}' detected. Consider using the native ${alternative}`
});
}
});
} else if (forbiddenImports.hasOwnProperty(node.source.value)) {
// ex: import indexOf from 'lodash/indexOf';
// ex: import indexOf from 'lodash.indexof';
context.report({
node,
message: `Import from '${node.source.value}' detected. Consider using the native ${alternative}`
});
}
}
};
}
};
}