eslint-plugin-lodash
Version:
Lodash specific linting rules for ESLint
90 lines (74 loc) • 3.78 kB
JavaScript
/**
* @fileoverview Rule to check if a _.filter condition or multiple filters should be _.overEvery or _.overSome
*/
;
/**
* @fileoverview Rule to check if a _.filter condition or multiple filters should be _.overEvery or _.overSome
*/
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
create: function create(context) {
var _require = require('../util/lodashUtil');
var getLodashMethodVisitors = _require.getLodashMethodVisitors;
var _require2 = require('../util/astUtil');
var getValueReturnedInFirstStatement = _require2.getValueReturnedInFirstStatement;
var getFirstParamName = _require2.getFirstParamName;
var isObjectOfMethodCall = _require2.isObjectOfMethodCall;
var getMethodName = _require2.getMethodName;
var _require3 = require('../util/methodDataUtil');
var isAliasOfMethod = _require3.isAliasOfMethod;
var conditionMethods = ['filter', 'reject', 'pickBy', 'omitBy', 'findIndex', 'findLastIndex', 'find', 'findLast', 'findKey', 'findLastKey'];
var message = 'Prefer _.{{method}} instead of a {{connective}}';
var reportConstants = {
'&&': {
method: 'overEvery',
connective: 'conjunction'
},
'||': {
method: 'overSome',
connective: 'disjunction'
}
};
function onlyPassesIdentifier(node) {
return node.arguments.length === 1 && node.arguments[0].type === 'Identifier';
}
function isOnlyParamInvocationsWithOperator(node, paramName, operator) {
if (node.type === 'CallExpression') {
return onlyPassesIdentifier(node) && node.arguments[0].name === paramName;
}
if (node.type === 'LogicalExpression') {
return node.operator === operator && isOnlyParamInvocationsWithOperator(node.left, paramName, operator) && isOnlyParamInvocationsWithOperator(node.right, paramName, operator);
}
}
function isCallToConditionMethod(method, version) {
return conditionMethods.some(function (m) {
return isAliasOfMethod(version, m, method);
});
}
function reportIfConnectiveOfParamInvocations(node) {
var retVal = getValueReturnedInFirstStatement(node);
var paramName = getFirstParamName(node);
if (retVal && retVal.type === 'LogicalExpression' && (retVal.operator === '&&' || retVal.operator === '||')) {
if (isOnlyParamInvocationsWithOperator(retVal, paramName, retVal.operator)) {
context.report(node, message, reportConstants[retVal.operator]);
}
}
}
function reportIfDoubleFilterLiteral(callType, iteratee, node, version) {
if (callType === 'chained' && iteratee.type === 'Identifier' && isObjectOfMethodCall(node) && isCallToConditionMethod(getMethodName(node.parent.parent), version) && onlyPassesIdentifier(node.parent.parent)) {
context.report(node, message, reportConstants['&&']);
}
}
return getLodashMethodVisitors(context, function (node, iteratee, _ref) {
var method = _ref.method;
var version = _ref.version;
var callType = _ref.callType;
if (isCallToConditionMethod(method, version)) {
reportIfConnectiveOfParamInvocations(iteratee);
reportIfDoubleFilterLiteral(callType, iteratee, node, version);
}
});
}
};