odin-javascript-exercises/node_modules/eslint-plugin-import/lib/rules/order.js

221 lines
25 KiB
JavaScript
Raw Normal View History

2017-12-15 10:56:14 -08:00
'use strict';
var _importType = require('../core/importType');
var _importType2 = _interopRequireDefault(_importType);
var _staticRequire = require('../core/staticRequire');
var _staticRequire2 = _interopRequireDefault(_staticRequire);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
// REPORTING
function reverse(array) {
return array.map(function (v) {
return {
name: v.name,
rank: -v.rank,
node: v.node
};
}).reverse();
}
function findOutOfOrder(imported) {
if (imported.length === 0) {
return [];
}
let maxSeenRankNode = imported[0];
return imported.filter(function (importedModule) {
const res = importedModule.rank < maxSeenRankNode.rank;
if (maxSeenRankNode.rank < importedModule.rank) {
maxSeenRankNode = importedModule;
}
return res;
});
}
function reportOutOfOrder(context, imported, outOfOrder, order) {
outOfOrder.forEach(function (imp) {
const found = imported.find(function hasHigherRank(importedItem) {
return importedItem.rank > imp.rank;
});
context.report(imp.node, '`' + imp.name + '` import should occur ' + order + ' import of `' + found.name + '`');
});
}
function makeOutOfOrderReport(context, imported) {
const outOfOrder = findOutOfOrder(imported);
if (!outOfOrder.length) {
return;
}
// There are things to report. Try to minimize the number of reported errors.
const reversedImported = reverse(imported);
const reversedOrder = findOutOfOrder(reversedImported);
if (reversedOrder.length < outOfOrder.length) {
reportOutOfOrder(context, reversedImported, reversedOrder, 'after');
return;
}
reportOutOfOrder(context, imported, outOfOrder, 'before');
}
// DETECTING
function computeRank(context, ranks, name, type) {
return ranks[(0, _importType2.default)(name, context)] + (type === 'import' ? 0 : 100);
}
function registerNode(context, node, name, type, ranks, imported) {
const rank = computeRank(context, ranks, name, type);
if (rank !== -1) {
imported.push({ name, rank, node });
}
}
function isInVariableDeclarator(node) {
return node && (node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent));
}
const types = ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'];
// Creates an object with type-rank pairs.
// Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
// Will throw an error if it contains a type that does not exist, or has a duplicate
function convertGroupsToRanks(groups) {
const rankObject = groups.reduce(function (res, group, index) {
if (typeof group === 'string') {
group = [group];
}
group.forEach(function (groupItem) {
if (types.indexOf(groupItem) === -1) {
throw new Error('Incorrect configuration of the rule: Unknown type `' + JSON.stringify(groupItem) + '`');
}
if (res[groupItem] !== undefined) {
throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
}
res[groupItem] = index;
});
return res;
}, {});
const omittedTypes = types.filter(function (type) {
return rankObject[type] === undefined;
});
return omittedTypes.reduce(function (res, type) {
res[type] = groups.length;
return res;
}, rankObject);
}
function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
const linesBetweenImports = context.getSourceCode().lines.slice(previousImport.node.loc.end.line, currentImport.node.loc.start.line - 1);
return linesBetweenImports.filter(line => !line.trim().length).length;
};
let previousImport = imported[0];
imported.slice(1).forEach(function (currentImport) {
const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
if (newlinesBetweenImports === 'always' || newlinesBetweenImports === 'always-and-inside-groups') {
if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
context.report(previousImport.node, 'There should be at least one empty line between import groups');
} else if (currentImport.rank === previousImport.rank && emptyLinesBetween > 0 && newlinesBetweenImports !== 'always-and-inside-groups') {
context.report(previousImport.node, 'There should be no empty line within import group');
}
} else {
if (emptyLinesBetween > 0) {
context.report(previousImport.node, 'There should be no empty line between import groups');
}
}
previousImport = currentImport;
});
}
module.exports = {
meta: {
docs: {},
schema: [{
type: 'object',
properties: {
groups: {
type: 'array'
},
'newlines-between': {
enum: ['ignore', 'always', 'always-and-inside-groups', 'never']
}
},
additionalProperties: false
}]
},
create: function importOrderRule(context) {
const options = context.options[0] || {};
const newlinesBetweenImports = options['newlines-between'] || 'ignore';
let ranks;
try {
ranks = convertGroupsToRanks(options.groups || defaultGroups);
} catch (error) {
// Malformed configuration
return {
Program: function (node) {
context.report(node, error.message);
}
};
}
let imported = [];
let level = 0;
function incrementLevel() {
level++;
}
function decrementLevel() {
level--;
}
return {
ImportDeclaration: function handleImports(node) {
if (node.specifiers.length) {
// Ignoring unassigned imports
const name = node.source.value;
registerNode(context, node, name, 'import', ranks, imported);
}
},
CallExpression: function handleRequires(node) {
if (level !== 0 || !(0, _staticRequire2.default)(node) || !isInVariableDeclarator(node.parent)) {
return;
}
const name = node.arguments[0].value;
registerNode(context, node, name, 'require', ranks, imported);
},
'Program:exit': function reportAndReset() {
makeOutOfOrderReport(context, imported);
if (newlinesBetweenImports !== 'ignore') {
makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
}
imported = [];
},
FunctionDeclaration: incrementLevel,
FunctionExpression: incrementLevel,
ArrowFunctionExpression: incrementLevel,
BlockStatement: incrementLevel,
ObjectExpression: incrementLevel,
'FunctionDeclaration:exit': decrementLevel,
'FunctionExpression:exit': decrementLevel,
'ArrowFunctionExpression:exit': decrementLevel,
'BlockStatement:exit': decrementLevel,
'ObjectExpression:exit': decrementLevel
};
}
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInJ1bGVzL29yZGVyLmpzIl0sIm5hbWVzIjpbImRlZmF1bHRHcm91cHMiLCJyZXZlcnNlIiwiYXJyYXkiLCJtYXAiLCJ2IiwibmFtZSIsInJhbmsiLCJub2RlIiwiZmluZE91dE9mT3JkZXIiLCJpbXBvcnRlZCIsImxlbmd0aCIsIm1heFNlZW5SYW5rTm9kZSIsImZpbHRlciIsImltcG9ydGVkTW9kdWxlIiwicmVzIiwicmVwb3J0T3V0T2ZPcmRlciIsImNvbnRleHQiLCJvdXRPZk9yZGVyIiwib3JkZXIiLCJmb3JFYWNoIiwiaW1wIiwiZm91bmQiLCJmaW5kIiwiaGFzSGlnaGVyUmFuayIsImltcG9ydGVkSXRlbSIsInJlcG9ydCIsIm1ha2VPdXRPZk9yZGVyUmVwb3J0IiwicmV2ZXJzZWRJbXBvcnRlZCIsInJldmVyc2VkT3JkZXIiLCJjb21wdXRlUmFuayIsInJhbmtzIiwidHlwZSIsInJlZ2lzdGVyTm9kZSIsInB1c2giLCJpc0luVmFyaWFibGVEZWNsYXJhdG9yIiwicGFyZW50IiwidHlwZXMiLCJjb252ZXJ0R3JvdXBzVG9SYW5rcyIsImdyb3VwcyIsInJhbmtPYmplY3QiLCJyZWR1Y2UiLCJncm91cCIsImluZGV4IiwiZ3JvdXBJdGVtIiwiaW5kZXhPZiIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsInVuZGVmaW5lZCIsIm9taXR0ZWRUeXBlcyIsIm1ha2VOZXdsaW5lc0JldHdlZW5SZXBvcnQiLCJuZXdsaW5lc0JldHdlZW5JbXBvcnRzIiwiZ2V0TnVtYmVyT2ZFbXB0eUxpbmVzQmV0d2VlbiIsImN1cnJlbnRJbXBvcnQiLCJwcmV2aW91c0ltcG9ydCIsImxpbmVzQmV0d2VlbkltcG9ydHMiLCJnZXRTb3VyY2VDb2RlIiwibGluZXMiLCJzbGljZSIsImxvYyIsImVuZCIsImxpbmUiLCJzdGFydCIsInRyaW0iLCJlbXB0eUxpbmVzQmV0d2VlbiIsIm1vZHVsZSIsImV4cG9ydHMiLCJtZXRhIiwiZG9jcyIsInNjaGVtYSIsInByb3BlcnRpZXMiLCJlbnVtIiwiYWRkaXRpb25hbFByb3BlcnRpZXMiLCJjcmVhdGUiLCJpbXBvcnRPcmRlclJ1bGUiLCJvcHRpb25zIiwiZXJyb3IiLCJQcm9ncmFtIiwibWVzc2FnZSIsImxldmVsIiwiaW5jcmVtZW50TGV2ZWwiLCJkZWNyZW1lbnRMZXZlbCIsIkltcG9ydERlY2xhcmF0aW9uIiwiaGFuZGxlSW1wb3J0cyIsInNwZWNpZmllcnMiLCJzb3VyY2UiLCJ2YWx1ZSIsIkNhbGxFeHByZXNzaW9uIiwiaGFuZGxlUmVxdWlyZXMiLCJhcmd1bWVudHMiLCJyZXBvcnRBbmRSZXNldCIsIkZ1bmN0aW9uRGVjbGFyYXRpb24iLCJGdW5jdGlvbkV4cHJlc3Npb24iLCJBcnJvd0Z1bmN0aW9uRXhwcmVzc2lvbiIsIkJsb2NrU3RhdGVtZW50IiwiT2JqZWN0RXhwcmVzc2lvbiJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsZ0JBQWdCLENBQUMsU0FBRCxFQUFZLFVBQVosRUFBd0IsUUFBeEIsRUFBa0MsU0FBbEMsRUFBNkMsT0FBN0MsQ0FBdEI7O0FBRUE7O0FBRUEsU0FBU0MsT0FBVCxDQUFpQkMsS0FBakIsRUFBd0I7QUFDdEIsU0FBT0EsTUFBTUMsR0FBTixDQUFVLFVBQVVDLENBQVYsRUFBYTtBQUM1QixXQUFPO0FBQ0xDLFlBQU1ELEVBQUVDLElBREg7QUFFTEMsWUFBTSxDQUFDRixFQUFFRSxJQUZKO0FBR0xDLFlBQU1ILEVBQUVHO0FBSEgsS0FBUDtBQUtELEdBTk0sRUFNSk4sT0FOSSxFQUFQO0FBT0Q7O0FBRUQsU0FBU08sY0FBVCxDQUF3QkMsUUFBeEIsRUFBa0M7QUFDaEMsTUFBSUEsU0FBU0MsTUFBVCxLQUFvQixDQUF4QixFQUEyQjtBQUN6QixXQUFPLEVBQVA7QUFDRDtBQUNELE1BQUlDLGtCQUFrQkYsU0FBUyxDQUFULENBQXRCO0FBQ0EsU0FBT0EsU0FBU0csTUFBVCxDQUFnQixVQUFVQyxjQUFWLEVBQTBCO0FBQy9DLFVBQU1DLE1BQU1ELGVBQWVQLElBQWYsR0FBc0JLLGdCQUFnQkwsSUFBbEQ7QUFDQSxRQUFJSyxnQkFBZ0JMLElBQWhCLEdBQXVCTyxlQUFlUCxJQUExQyxFQUFnRDtBQUM5Q0ssd0JBQWtCRSxjQUFsQjtBQUNEO0FBQ0QsV0FBT0MsR0FBUDtBQUNELEdBTk0sQ0FBUDtBQU9EOztBQUVELFNBQVNDLGdCQUFULENBQTBCQyxPQUExQixFQUFtQ1AsUUFBbkMsRUFBNkNRLFVBQTdDLEVBQXlEQyxLQUF6RCxFQUFnRTtBQUM5REQsYUFBV0UsT0FBWCxDQUFtQixVQUFVQyxHQUFWLEVBQWU7QUFDaEMsVUFBTUMsUUFBUVosU0FBU2EsSUFBVCxDQUFjLFNBQVNDLGFBQVQsQ0FBdUJDLFlBQXZCLEVBQXFDO0FBQy9ELGFBQU9BLGFBQWFsQixJQUFiLEdBQW9CYyxJQUFJZCxJQUEvQjtBQUNELEtBRmEsQ0FBZDtBQUdBVSxZQUFRUyxNQUFSLENBQWVMLElBQUliLElBQW5CLEVBQXlCLE1BQU1hLElBQUlmLElBQVYsR0FBaUIsd0JBQWpCLEdBQTRDYSxLQUE1QyxHQUN2QixjQUR1QixHQUNORyxNQUFNaEIsSUFEQSxHQUNPLEdBRGhDO0FBRUQsR0FORDtBQU9EOztBQUVELFNBQVNxQixvQkFBVCxDQUE4QlYsT0FBOUIsRUFBdUNQLFFBQXZDLEVBQWlEO0FBQy9DLFFBQU1RLGFBQWFULGVBQWVDLFFBQWYsQ0FBbkI7QUFDQSxNQUFJLENBQUNRLFdBQVdQLE1BQWhCLEVBQXdCO0FBQ3RCO0FBQ0Q7QUFDRDtBQUNBLFFBQU1pQixtQkFBbUIxQixRQUFRUSxRQUFSLENBQXpCO0FBQ0EsUUFBTW1CLGdCQUFnQnBCLGVBQWVtQixnQkFBZixDQUF0QjtBQUNBLE1BQUlDLGNBQWNsQixNQUFkLEdBQXVCTyxXQUFXUCxNQUF0QyxFQUE4QztBQUM1Q0sscUJBQWlCQyxPQUFqQixFQUEwQlcsZ0JBQTFCLEVBQTRDQyxhQUE1QyxFQUEyRCxPQUEzRDtBQUNBO0FBQ0Q7QUFDRGIsbUJBQWlCQyxPQUFqQixFQUEwQlAsUUFBMUIsRUFBb0NRLFVBQXBDLEVBQWdELFFBQWhEO0FBQ0Q7O0FBRUQ7O0FBRUEsU0FBU1ksV0FBVCxDQUFxQmIsT0FBckIsRUFBOEJjLEtBQTlCLEVBQXFDekIsSUFBckMsRUFBMkMwQixJQUEzQyxFQUFpRDtBQUMvQyxTQUFPRCxNQUFNLDBCQUFXekIsSUFBWCxFQUFpQlcsT0FBakIsQ0FBTixLQUNKZSxTQUFTLFFBQVQsR0FBb0IsQ0FBcEIsR0FBd0IsR0FEcEIsQ0FBUDtBQUVEOztBQUVELFNBQVNDLFlBQVQsQ0FBc0JoQixPQUF0QixFQUErQlQsSUFBL0IsRUFBcUNGLElBQXJDLEVBQTJDMEIsSUFBM0MsRUFBaURELEtBQWpELEVBQXdEckIsUUFBeEQsRUFBa0U7QUFDaEUsUUFBTUgsT0FBT3VCLFlBQVliLE9BQVo