eslint-plugin-ferramentas
Version:
A bundle of useful ESLint rules
123 lines (122 loc) • 4.89 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.rule = exports.ruleName = void 0;
const path_1 = require("path");
const Utils_1 = require("../Utils");
exports.ruleName = 'relative-import-order';
const extractOptions = (directory, [firstOption]) => {
const { directories, ignore = [], isRelative = Utils_1.RELATIVE_IMPORT_PATTERN, debug = false, } = firstOption;
return {
ignore: ignore.map((relativePath) => (0, path_1.resolve)(directory, relativePath)),
directories: directories.map((relativePath) => (0, path_1.resolve)(directory, relativePath)),
isRelative: new RegExp(isRelative),
debug,
};
};
/**
* @returns the position an import should have *if* it is not ignored
* - number for the actual position
* - true if it was ignored
* - false if no match is founf
*/
const resolvePositionFromConfig = ({ directories, ignore }, importPath) => {
const indexPos = directories.findIndex((directory) => importPath.startsWith(directory));
if (indexPos >= 0) {
/**
* Position from config found
*/
return indexPos;
}
if (ignore.some((directory) => importPath.startsWith(directory))) {
/**
* Import is ignored
*/
return true;
}
return false;
};
const reportOutOfOrder = (context, node, lastNode) => context.report({
node,
message: `Imports from '${(0, Utils_1.extractImportPath)(node)}' should be above the import from '${(0, Utils_1.extractImportPath)(lastNode)}'`,
/** Swap imports */
fix: (fixer) => [
fixer.replaceText(node, context.getSourceCode().getText(lastNode)),
fixer.replaceText(lastNode, context.getSourceCode().getText(node)),
],
});
const reportNonListed = (context, node) => context.report({
node,
message: [
`The path '${(0, Utils_1.extractImportPath)(node)}' is not listed on the ESLINT rule '${exports.ruleName}'.`,
`If '${exports.ruleName}' is enabled then all imported paths need to be included,`,
'if you do not wish to order this import, add it to the ignored list',
].join('\n'),
});
exports.rule = {
meta: {
type: 'layout',
fixable: 'code',
hasSuggestions: true,
docs: { description: 'enforces a ordering of relative imports, so they follow a consistent structure across all files' },
schema: {
type: 'array',
items: {
type: 'object',
properties: {
directories: { type: 'array', items: { type: 'string' } },
ignore: { type: 'array', items: { type: 'string' } },
isRelative: { type: 'string' },
debug: { type: 'boolean' },
},
required: ['directories'],
additionalProperties: false,
},
minItems: 1,
maxItems: 1,
},
},
create: (context) => {
const workingDirectory = context.getCwd();
const currentDirectory = (0, path_1.dirname)(context.getFilename());
const options = extractOptions(workingDirectory, context.options);
const debug = (0, Utils_1.createDebugger)(options.debug);
debug('workingDirectory', workingDirectory);
debug('currentDirectory', currentDirectory);
debug('options', options);
let lastAux = null;
return {
ImportDeclaration: (node) => {
const importPath = (0, Utils_1.extractImportPath)(node);
debug('importPath', importPath);
const isRelative = options.isRelative.test(importPath);
debug('isRelative', isRelative);
if (!isRelative) {
/**
* If its a module, just give up
*/
return;
}
const position = resolvePositionFromConfig(options, (0, path_1.resolve)(currentDirectory, importPath));
debug('position', position);
debug('lastAux.position', lastAux === null || lastAux === void 0 ? void 0 : lastAux.position);
if (position === true) {
/**
* Import is in the ignored list
*/
return;
}
if (position === false) {
reportNonListed(context, node);
return;
}
if (lastAux !== null && lastAux.position !== null && lastAux.position > position) {
/**
* If their position is swapped, then report
*/
reportOutOfOrder(context, node, lastAux.node);
}
lastAux = { position, node };
},
};
},
};
;