@lesnoypudge/eslint-plugin-import-export
Version:
lesnoypudge's eslint-plugin-import-export
214 lines (213 loc) • 6.14 kB
JavaScript
import { never, invariant } from "@lesnoypudge/utils";
import { messageIds } from "./extra.js";
import * as t from "@babel/types";
import { generate } from "@babel/generator";
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
const tt = AST_NODE_TYPES;
const padded = (text) => {
return " ".repeat(4) + text;
};
const getImportAst = (node) => {
const ast = t.importDeclaration(
node.specifiers.map((clause) => {
switch (clause.type) {
case tt.ImportSpecifier: {
const original = clause.imported.type === tt.Identifier ? clause.imported.name : clause.imported.value;
return t.importSpecifier(
t.identifier(original),
t.identifier(clause.local.name)
);
}
case tt.ImportDefaultSpecifier: {
return t.importDefaultSpecifier(
t.identifier(clause.local.name)
);
}
default: {
never("unhandled import specifier");
}
}
}),
t.stringLiteral(node.source.value)
);
return ast;
};
const getExportAst = (node) => {
var _a;
invariant((_a = node.source) == null ? void 0 : _a.value);
const ast = t.exportNamedDeclaration(
null,
node.specifiers.map((clause) => {
const local = clause.local.type === tt.Literal ? clause.local.value : clause.local.name;
const exported = clause.exported.type === tt.Literal ? clause.exported.value : clause.exported.name;
return t.exportSpecifier(
t.identifier(local),
t.identifier(exported)
);
}),
t.stringLiteral(node.source.value)
);
return ast;
};
const getOneLinerImport = (node) => {
return generate(getImportAst(node)).code.replaceAll('"', "'");
};
const getOneLinerExport = (node) => {
return generate(getExportAst(node)).code.replaceAll('"', "'");
};
const getMultilineImport = (node) => {
const ast = getImportAst(node);
const first = ast.specifiers[0];
invariant(first);
const withDefault = t.isImportDefaultSpecifier(first);
const defaultName = withDefault ? first.local.name + ", " : "";
const rest = withDefault ? ast.specifiers.slice(1) : ast.specifiers;
return [
`import ${defaultName}{`,
...rest.map((clause) => {
invariant(t.isImportSpecifier(clause));
const imported = t.isStringLiteral(clause.imported) ? clause.imported.value : clause.imported.name;
const local = clause.local.name;
if (imported !== local) {
return padded(`${local} as ${imported},`);
}
return `${padded(imported)},`;
}),
`} from '${ast.source.value}';`
].join("\n");
};
const getMultilineExport = (node) => {
const ast = getExportAst(node);
const source = ast.source ? ` from '${ast.source.value}'` : "";
return [
`export {`,
...ast.specifiers.map((clause) => {
invariant(t.isExportSpecifier(clause));
const exported = t.isStringLiteral(clause.exported) ? clause.exported.value : clause.exported.name;
const local = clause.local.name;
if (exported !== local) {
return padded(`${local} as ${exported},`);
}
return `${padded(exported)},`;
}),
`}${source};`
].join("\n");
};
const ruleVisitors = (context) => {
const getIsMultiline = (node) => {
return context.sourceCode.getText(node).split("\n").length > 1;
};
const getIsExceeds = (length) => {
return length > 80;
};
const getConditions = ({
isExceeds,
node
}) => {
const isMultiline = getIsMultiline(node);
const isOneLiner = !isMultiline;
const shouldTransformToOneLiner = isMultiline && !isExceeds;
const shouldTransformToMultiline = isOneLiner && isExceeds;
const shouldBail = !shouldTransformToMultiline && !shouldTransformToOneLiner;
return {
shouldTransformToMultiline,
shouldTransformToOneLiner,
shouldBail
};
};
const handleImportDeclaration = (node) => {
const withSpecifiers = node.specifiers.some((clause) => {
return clause.type === tt.ImportSpecifier;
});
if (!withSpecifiers) return;
const isExceeds = getIsExceeds(
getOneLinerImport(node).length
);
const {
shouldBail,
shouldTransformToMultiline,
shouldTransformToOneLiner
} = getConditions({ isExceeds, node });
if (shouldBail) return;
if (shouldTransformToMultiline) {
return context.report({
messageId: messageIds.longOneLiner,
node,
fix: (fixer) => {
return fixer.replaceText(
node,
getMultilineImport(node)
);
}
});
}
if (shouldTransformToOneLiner) {
return context.report({
messageId: messageIds.shortMultiline,
node,
fix: (fixer) => {
return fixer.replaceText(
node,
getOneLinerImport(node)
);
}
});
}
never();
};
const handleExportNamedDeclaration = (node) => {
if (node.declaration !== null) return;
const isExceeds = getIsExceeds(
getOneLinerExport(node).length
);
const {
shouldBail,
shouldTransformToMultiline,
shouldTransformToOneLiner
} = getConditions({ isExceeds, node });
if (shouldBail) return;
if (shouldTransformToMultiline) {
return context.report({
messageId: messageIds.longOneLiner,
node,
fix: (fixer) => {
return fixer.replaceText(
node,
getMultilineExport(node)
);
}
});
}
if (shouldTransformToOneLiner) {
return context.report({
messageId: messageIds.shortMultiline,
node,
fix: (fixer) => {
return fixer.replaceText(
node,
getOneLinerExport(node)
);
}
});
}
never();
};
return {
[tt.ImportDeclaration]: (node) => {
try {
handleImportDeclaration(node);
} catch {
}
},
[tt.ExportNamedDeclaration]: (node) => {
try {
handleExportNamedDeclaration(node);
} catch {
}
}
};
};
export {
ruleVisitors
};
//# sourceMappingURL=ruleVisitors.js.map