eslint-plugin-lodash
Version:
Lodash specific linting rules for ESLint
90 lines (72 loc) • 3.19 kB
JavaScript
/**
* @fileoverview Rule to check if the expression could be better expressed as a chain
*/
;
/**
* @fileoverview Rule to check if the expression could be better expressed as a chain
*/
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
schema: [{
enum: ['always', 'never']
}, {
type: 'integer',
minimum: 2
}]
},
create: function create(context) {
var _require = require('../util/lodashUtil');
var isLodashCall = _require.isLodashCall;
var getLodashImportVisitors = _require.getLodashImportVisitors;
var isLodashChainStart = _require.isLodashChainStart;
var getImportedLodashMethod = _require.getImportedLodashMethod;
var isChainBreaker = _require.isChainBreaker;
var _require2 = require('../util/astUtil');
var getCaller = _require2.getCaller;
var isMethodCall = _require2.isMethodCall;
var isObjectOfMethodCall = _require2.isObjectOfMethodCall;
var _require3 = require('../util/ruleUtil');
var combineVisitorObjects = _require3.combineVisitorObjects;
var DEFAULT_LENGTH = 3;
var _require$getSettings = require('../util/settingsUtil').getSettings(context);
var pragma = _require$getSettings.pragma;
var version = _require$getSettings.version;
var negate = require('lodash/negate');
var mode = context.options[0] || 'never';
var ruleDepth = parseInt(context.options[1], 10) || DEFAULT_LENGTH;
var isEndOfChain = negate(isObjectOfMethodCall);
function isBeforeChainBreaker(node) {
return isChainBreaker(node.parent.parent, version);
}
function isNestedNLevels(node, n) {
if (n === 0) {
return true;
} else if (isLodashCall(node, pragma, context) || getImportedLodashMethod(context, node)) {
return isNestedNLevels(node.arguments[0], n - 1);
}
}
var callExpressionVisitors = {
always: function always(node) {
if (isNestedNLevels(node, ruleDepth)) {
context.report(getCaller(node.arguments[0]), 'Prefer chaining to composition');
} else if (isLodashChainStart(node, pragma, context)) {
var firstCall = node.parent.parent;
if (isMethodCall(firstCall) && (isEndOfChain(firstCall) || isBeforeChainBreaker(firstCall))) {
context.report(firstCall, 'Do not use chain syntax for single method');
}
}
},
never: function never(node) {
if (isLodashChainStart(node, pragma, context)) {
context.report(node, 'Prefer composition to Lodash chaining');
}
}
};
return combineVisitorObjects({
CallExpression: callExpressionVisitors[mode]
}, getLodashImportVisitors(context));
}
};