@truenine/eslint9-config
Version:
ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support
82 lines (80 loc) • 3.14 kB
JavaScript
//#region src/rules/single-line/call.ts
const MAX_LINE_LENGTH = 160;
const rule = {
meta: {
type: "layout",
docs: {
description: "Prefer single-line function calls when the result fits within max line length",
recommended: false
},
fixable: "code",
schema: [{
type: "object",
properties: { maxLineLength: {
type: "number",
default: MAX_LINE_LENGTH
} },
additionalProperties: false
}],
messages: { preferSingleLineCall: "Function call can be written on a single line" }
},
create(context) {
const { sourceCode } = context;
const maxLineLength = (context.options[0] ?? {}).maxLineLength ?? MAX_LINE_LENGTH;
function hasComments(node) {
return sourceCode.getCommentsInside(node).length > 0;
}
function isNodeMultiLine(node) {
return node.loc.start.line !== node.loc.end.line;
}
function normalizeText(text) {
return text.split("\n").map((l) => l.trim()).join(" ").replaceAll(/\s+/g, " ").trim();
}
function getIndent(node) {
const line = sourceCode.lines[node.loc.start.line - 1];
return /^(\s*)/.exec(line)?.[1] ?? "";
}
function hasNestedObjectLiteral(node) {
if (node.type !== "ObjectExpression") return false;
const objNode = node;
for (const prop of objNode.properties) if (prop.type === "Property" && (prop.value?.type === "ObjectExpression" || prop.value?.type === "ArrayExpression")) return true;
return false;
}
function hasComplexArgument(args) {
for (const arg of args) {
if (["ArrowFunctionExpression", "FunctionExpression"].includes(arg.type)) return true;
if (arg.type === "TemplateLiteral" && sourceCode.getText(arg).includes("\n")) return true;
if (arg.type === "ObjectExpression") {
if (arg.properties.length >= 5 || hasNestedObjectLiteral(arg)) return true;
}
if (arg.type === "ArrayExpression" && arg.elements.length >= 4) return true;
if (arg.type === "CallExpression" && hasComplexArgument(arg.arguments)) return true;
}
return false;
}
function isPartOfChainedCall(node) {
const { parent } = node;
return parent?.type === "MemberExpression" && parent.parent?.type === "CallExpression";
}
function isChainedMethodCall(node) {
const callNode = node;
return callNode.callee.type === "MemberExpression" && callNode.callee.object.type === "CallExpression";
}
return { CallExpression(node) {
const callNode = node;
if (!isNodeMultiLine(callNode) || hasComments(callNode) || hasComplexArgument(callNode.arguments) || isPartOfChainedCall(callNode) || isChainedMethodCall(callNode)) return;
if (callNode.loc.end.line - callNode.loc.start.line + 1 > 4) return;
const singleLineText = `${sourceCode.getText(callNode.callee)}(${callNode.arguments.map((arg) => normalizeText(sourceCode.getText(arg))).join(", ")})`;
if (singleLineText.length > 80) return;
if (getIndent(callNode).length + singleLineText.length > maxLineLength) return;
context.report({
node,
messageId: "preferSingleLineCall",
fix: (fixer) => fixer.replaceText(node, singleLineText)
});
} };
}
};
//#endregion
module.exports = rule;
//# sourceMappingURL=call.cjs.map