160 lines
14 KiB
JavaScript
160 lines
14 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var _docsUrl = require('../docsUrl');
|
||
|
|
||
|
var _docsUrl2 = _interopRequireDefault(_docsUrl);
|
||
|
|
||
|
var _object = require('object.values');
|
||
|
|
||
|
var _object2 = _interopRequireDefault(_object);
|
||
|
|
||
|
var _arrayPrototype = require('array.prototype.flat');
|
||
|
|
||
|
var _arrayPrototype2 = _interopRequireDefault(_arrayPrototype);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
const meta = {
|
||
|
type: 'suggestion',
|
||
|
docs: {
|
||
|
url: (0, _docsUrl2.default)('group-exports')
|
||
|
}
|
||
|
/* eslint-disable max-len */
|
||
|
};const errors = {
|
||
|
ExportNamedDeclaration: 'Multiple named export declarations; consolidate all named exports into a single export declaration',
|
||
|
AssignmentExpression: 'Multiple CommonJS exports; consolidate all exports into a single assignment to `module.exports`'
|
||
|
/* eslint-enable max-len */
|
||
|
|
||
|
/**
|
||
|
* Returns an array with names of the properties in the accessor chain for MemberExpression nodes
|
||
|
*
|
||
|
* Example:
|
||
|
*
|
||
|
* `module.exports = {}` => ['module', 'exports']
|
||
|
* `module.exports.property = true` => ['module', 'exports', 'property']
|
||
|
*
|
||
|
* @param {Node} node AST Node (MemberExpression)
|
||
|
* @return {Array} Array with the property names in the chain
|
||
|
* @private
|
||
|
*/
|
||
|
};function accessorChain(node) {
|
||
|
const chain = [];
|
||
|
|
||
|
do {
|
||
|
chain.unshift(node.property.name);
|
||
|
|
||
|
if (node.object.type === 'Identifier') {
|
||
|
chain.unshift(node.object.name);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
node = node.object;
|
||
|
} while (node.type === 'MemberExpression');
|
||
|
|
||
|
return chain;
|
||
|
}
|
||
|
|
||
|
function create(context) {
|
||
|
const nodes = {
|
||
|
modules: {
|
||
|
set: new Set(),
|
||
|
sources: {}
|
||
|
},
|
||
|
types: {
|
||
|
set: new Set(),
|
||
|
sources: {}
|
||
|
},
|
||
|
commonjs: {
|
||
|
set: new Set()
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
ExportNamedDeclaration(node) {
|
||
|
let target = node.exportKind === 'type' ? nodes.types : nodes.modules;
|
||
|
if (!node.source) {
|
||
|
target.set.add(node);
|
||
|
} else if (Array.isArray(target.sources[node.source.value])) {
|
||
|
target.sources[node.source.value].push(node);
|
||
|
} else {
|
||
|
target.sources[node.source.value] = [node];
|
||
|
}
|
||
|
},
|
||
|
|
||
|
AssignmentExpression(node) {
|
||
|
if (node.left.type !== 'MemberExpression') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const chain = accessorChain(node.left);
|
||
|
|
||
|
// Assignments to module.exports
|
||
|
// Deeper assignments are ignored since they just modify what's already being exported
|
||
|
// (ie. module.exports.exported.prop = true is ignored)
|
||
|
if (chain[0] === 'module' && chain[1] === 'exports' && chain.length <= 3) {
|
||
|
nodes.commonjs.set.add(node);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Assignments to exports (exports.* = *)
|
||
|
if (chain[0] === 'exports' && chain.length === 2) {
|
||
|
nodes.commonjs.set.add(node);
|
||
|
return;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
'Program:exit': function onExit() {
|
||
|
// Report multiple `export` declarations (ES2015 modules)
|
||
|
if (nodes.modules.set.size > 1) {
|
||
|
nodes.modules.set.forEach(node => {
|
||
|
context.report({
|
||
|
node,
|
||
|
message: errors[node.type]
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Report multiple `aggregated exports` from the same module (ES2015 modules)
|
||
|
(0, _arrayPrototype2.default)((0, _object2.default)(nodes.modules.sources).filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)).forEach(node => {
|
||
|
context.report({
|
||
|
node,
|
||
|
message: errors[node.type]
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Report multiple `export type` declarations (FLOW ES2015 modules)
|
||
|
if (nodes.types.set.size > 1) {
|
||
|
nodes.types.set.forEach(node => {
|
||
|
context.report({
|
||
|
node,
|
||
|
message: errors[node.type]
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Report multiple `aggregated type exports` from the same module (FLOW ES2015 modules)
|
||
|
(0, _arrayPrototype2.default)((0, _object2.default)(nodes.types.sources).filter(nodesWithSource => Array.isArray(nodesWithSource) && nodesWithSource.length > 1)).forEach(node => {
|
||
|
context.report({
|
||
|
node,
|
||
|
message: errors[node.type]
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Report multiple `module.exports` assignments (CommonJS)
|
||
|
if (nodes.commonjs.set.size > 1) {
|
||
|
nodes.commonjs.set.forEach(node => {
|
||
|
context.report({
|
||
|
node,
|
||
|
message: errors[node.type]
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
meta,
|
||
|
create
|
||
|
};
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9ncm91cC1leHBvcnRzLmpzIl0sIm5hbWVzIjpbIm1ldGEiLCJ0eXBlIiwiZG9jcyIsInVybCIsImVycm9ycyIsIkV4cG9ydE5hbWVkRGVjbGFyYXRpb24iLCJBc3NpZ25tZW50RXhwcmVzc2lvbiIsImFjY2Vzc29yQ2hhaW4iLCJub2RlIiwiY2hhaW4iLCJ1bnNoaWZ0IiwicHJvcGVydHkiLCJuYW1lIiwib2JqZWN0IiwiY3JlYXRlIiwiY29udGV4dCIsIm5vZGVzIiwibW9kdWxlcyIsInNldCIsIlNldCIsInNvdXJjZXMiLCJ0eXBlcyIsImNvbW1vbmpzIiwidGFyZ2V0IiwiZXhwb3J0S2luZCIsInNvdXJjZSIsImFkZCIsIkFycmF5IiwiaXNBcnJheSIsInZhbHVlIiwicHVzaCIsImxlZnQiLCJsZW5ndGgiLCJvbkV4aXQiLCJzaXplIiwiZm9yRWFjaCIsInJlcG9ydCIsIm1lc3NhZ2UiLCJmaWx0ZXIiLCJub2Rlc1dpdGhTb3VyY2UiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0FBRUEsTUFBTUEsT0FBTztBQUNYQyxRQUFNLFlBREs7QUFFWEMsUUFBTTtBQUNKQyxTQUFLLHVCQUFRLGVBQVI7QUFERDtBQUlSO0FBTmEsQ0FBYixDQU9BLE1BQU1DLFNBQVM7QUFDYkMsMEJBQXdCLG9HQURYO0FBRWJDLHdCQUFzQjtBQUV4Qjs7QUFFQTs7Ozs7Ozs7Ozs7O0FBTmUsQ0FBZixDQWtCQSxTQUFTQyxhQUFULENBQXVCQyxJQUF2QixFQUE2QjtBQUMzQixRQUFNQyxRQUFRLEVBQWQ7O0FBRUEsS0FBRztBQUNEQSxVQUFNQyxPQUFOLENBQWNGLEtBQUtHLFFBQUwsQ0FBY0MsSUFBNUI7O0FBRUEsUUFBSUosS0FBS0ssTUFBTCxDQUFZWixJQUFaLEtBQXFCLFlBQXpCLEVBQXVDO0FBQ3JDUSxZQUFNQyxPQUFOLENBQWNGLEtBQUtLLE1BQUwsQ0FBWUQsSUFBMUI7QUFD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
|