UNPKG

@truenine/eslint9-config

Version:

ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support

118 lines (116 loc) 4.78 kB
//#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 module.exports = rule; //# sourceMappingURL=compact-try-catch.cjs.map