@truenine/eslint9-config
Version:
ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support
117 lines (116 loc) • 4.79 kB
JavaScript
//#region src/rules/code-style/compact-try-catch.ts
const MAX_SINGLE_LINE_LENGTH = 120;
const rule = {
meta: {
type: "layout",
docs: {
description: "Enforce compact try-catch-finally layout with independent block optimization",
recommended: false
},
fixable: "whitespace",
messages: {
compactCatch: "Catch clause should be on the same line as the try block's closing brace",
compactFinally: "Finally clause should be on the same line as the previous block's closing brace",
preferSingleLineTry: "Try block should be compressed to a single line",
preferSingleLineCatch: "Catch block should be compressed to a single line",
preferSingleLineFinally: "Finally block should be compressed to a single line"
},
schema: []
},
create(context) {
const { sourceCode } = context;
function isSingleLine(node) {
const { loc } = node;
if (!loc) return false;
return loc.start.line === loc.end.line;
}
function canBeSingleLine(block) {
if (block?.type !== "BlockStatement") return false;
const bNode = block;
const { body } = bNode;
if (body.length === 0) return true;
if (body.length > 1) return false;
const stmt = body[0];
if (![
"ExpressionStatement",
"ReturnStatement",
"ThrowStatement",
"BreakStatement",
"ContinueStatement"
].includes(stmt.type)) return false;
const stmtLoc = stmt.loc;
if (!stmtLoc || stmtLoc.start.line !== stmtLoc.end.line) return false;
if (sourceCode.getText(stmt).trim().length > 100) return false;
if (getCompactBlockText(bNode).length > MAX_SINGLE_LINE_LENGTH) return false;
return true;
}
function getCompactBlockText(block) {
const { body } = block;
if (body.length === 0) return "{}";
return `{ ${sourceCode.getText(body[0]).trim().replace(/;$/, "")}; }`;
}
return { TryStatement(node) {
const tryNode = node;
const tryBlock = tryNode.block;
const { handler, finalizer } = tryNode;
const tryCanBeSingle = canBeSingleLine(tryBlock);
const tryIsSingle = isSingleLine(tryBlock);
if (tryCanBeSingle && !tryIsSingle) context.report({
node: tryBlock,
messageId: "preferSingleLineTry",
fix: (fixer) => fixer.replaceTextRange(tryBlock.range, getCompactBlockText(tryBlock))
});
if (handler !== null) {
const catchBlock = handler.body;
const catchCanBeSingle = canBeSingleLine(catchBlock);
const catchIsSingle = isSingleLine(catchBlock);
if (catchCanBeSingle && !catchIsSingle) context.report({
node: catchBlock,
messageId: "preferSingleLineCatch",
fix: (fixer) => fixer.replaceTextRange(catchBlock.range, getCompactBlockText(catchBlock))
});
if (!tryIsSingle && !tryCanBeSingle && !catchIsSingle && !catchCanBeSingle) {
const tryCloseBrace = sourceCode.getLastToken(tryBlock);
const catchToken = sourceCode.getFirstToken(handler);
if (tryCloseBrace !== null && catchToken !== null && tryCloseBrace.loc !== null && catchToken.loc !== null) {
if (tryCloseBrace.loc.end.line !== catchToken.loc.start.line) {
const spaceBefore = sourceCode.getTokenBefore(catchToken);
if (spaceBefore !== null) context.report({
node: catchToken,
messageId: "compactCatch",
fix: (fixer) => fixer.replaceTextRange([spaceBefore.range[1], catchToken.range[0]], " ")
});
}
}
}
}
if (finalizer === null) return;
const finallyBlock = finalizer;
const finallyCanBeSingle = canBeSingleLine(finallyBlock);
const finallyIsSingle = isSingleLine(finallyBlock);
if (finallyCanBeSingle && !finallyIsSingle) context.report({
node: finallyBlock,
messageId: "preferSingleLineFinally",
fix: (fixer) => fixer.replaceTextRange(finallyBlock.range, getCompactBlockText(finallyBlock))
});
const previousBlock = handler !== null ? handler.body : tryBlock;
const prevCanBeSingle = canBeSingleLine(previousBlock);
if (!(!isSingleLine(previousBlock) && !prevCanBeSingle) || !(!finallyIsSingle && !finallyCanBeSingle)) return;
const prevCloseBrace = sourceCode.getLastToken(previousBlock);
const finallyToken = sourceCode.getFirstTokenBetween(handler ?? tryBlock, finallyBlock, (t) => t.value === "finally");
if (prevCloseBrace !== null && finallyToken !== null && prevCloseBrace.loc !== null && finallyToken.loc !== null) {
if (prevCloseBrace.loc.end.line !== finallyToken.loc.start.line) {
const spaceBefore = sourceCode.getTokenBefore(finallyToken);
if (spaceBefore !== null) context.report({
node: finallyToken,
messageId: "compactFinally",
fix: (fixer) => fixer.replaceTextRange([spaceBefore.range[1], finallyToken.range[0]], " ")
});
}
}
} };
}
};
//#endregion
export { rule as default };
//# sourceMappingURL=compact-try-catch.mjs.map