UNPKG

eslint-plugin-eslint-config

Version:
132 lines (105 loc) 4.01 kB
"use strict"; var _experimentalUtils = require("@typescript-eslint/experimental-utils"); const getPropertyName = node => { const key = node.key; switch (key.type) { case _experimentalUtils.AST_NODE_TYPES.Literal: return String(key.value); case _experimentalUtils.AST_NODE_TYPES.TemplateLiteral: if (key.expressions.length === 0 && key.quasis.length === 1) { return key.quasis[0].value.cooked; } break; case _experimentalUtils.AST_NODE_TYPES.Identifier: break; // no default } return null; }; const trimPluginName = rule => { return rule.substring(rule.indexOf('/')); }; const isRuleSorted = (a, b) => { if (a.includes('/') && b.includes('/')) { return a <= b; } return trimPluginName(a) <= trimPluginName(b); }; const isPropertyInRulesConfig = node => { var _node$parent, _node$parent$parent; return Boolean(((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : (_node$parent$parent = _node$parent.parent) === null || _node$parent$parent === void 0 ? void 0 : _node$parent$parent.type) === _experimentalUtils.AST_NODE_TYPES.Property && node.parent.parent.key.type === _experimentalUtils.AST_NODE_TYPES.Identifier && node.parent.parent.key.name === 'rules'); }; module.exports = _experimentalUtils.ESLintUtils.RuleCreator(name => name)({ name: __filename, meta: { type: 'problem', docs: { description: 'Ensures that rules are sorted in a consistent order', category: 'Best Practices', recommended: false }, fixable: 'code', messages: { incorrectOrder: "Rules should be in ascending order, with core rules last. '{{ thisName }}' should be before '{{ prevName }}'." }, schema: [] }, defaultOptions: [], create(context) { // The stack to save the previous property's name for each object literals. let stack = null; return { [_experimentalUtils.AST_NODE_TYPES.ObjectExpression](node) { stack = { upper: stack, prevName: null, prevNode: null, numKeys: node.properties.length }; }, [`${_experimentalUtils.AST_NODE_TYPES.ObjectExpression}:exit`]() { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion stack = stack.upper; }, [_experimentalUtils.AST_NODE_TYPES.SpreadElement](node) { var _node$parent2; if (((_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.type) === _experimentalUtils.AST_NODE_TYPES.ObjectExpression && stack) { stack.prevName = null; } }, [_experimentalUtils.AST_NODE_TYPES.Property](node) { var _node$parent3, _stack$prevNode; if (((_node$parent3 = node.parent) === null || _node$parent3 === void 0 ? void 0 : _node$parent3.type) === _experimentalUtils.AST_NODE_TYPES.ObjectPattern || !isPropertyInRulesConfig(node) || !stack) { return; } const prevName = stack.prevName; const prevNode = (_stack$prevNode = stack.prevNode) !== null && _stack$prevNode !== void 0 ? _stack$prevNode : node; const thisName = getPropertyName(node); if (thisName !== null) { stack.prevName = thisName; stack.prevNode = node; } if (prevName === null || thisName === null) { return; } if (!isRuleSorted(prevName, thisName)) { context.report({ messageId: 'incorrectOrder', data: { thisName, prevName }, node, loc: node.key.loc, fix(fixer) { const sourceCode = context.getSourceCode(); const thisText = sourceCode.getText(node); const prevText = sourceCode.getText(prevNode); return [fixer.replaceText(node, prevText), fixer.replaceText(prevNode, thisText)]; } }); } } }; } });