UNPKG

eslint-plugin-exception-handling

Version:

💣 Lints unhandled functions that might throw errors. For JavaScript/TypeScript eslint.

87 lines (86 loc) • 2.97 kB
import { isIdentifier } from "@typescript-eslint/utils/ast-utils"; import { findInParent, isCallExpression, isThrowStatement, isTryStatement, findInChildren, exploreChildren, getFunctionId, resolveFunc, isCatchClause, } from "../../src/utils/index.js"; import { nativeThrowing } from "../../src/utils/native-throwing.js"; const throwFunctions = new Set(); const scannedFunctions = new Set(); const getNodeId = (node, context) => [ node.type, node.name, node.id?.name, node.loc?.start.line, node.loc?.end.line, node.loc?.start.column, node.loc?.end.column, context.filename, ].join(" "); export function canFuncThrowClear() { throwFunctions.clear(); scannedFunctions.clear(); } const checked = {}; export function canFuncThrow(node, context) { const nodeId = getNodeId(node, context); if (checked[nodeId] != undefined) return checked[nodeId]; const try_ = findInParent(node, isTryStatement); if (try_) { checked[nodeId] = false; return false; } const res = resolveFunc(node, context); if (res?.module) { const found = nativeThrowing.some((x) => x.module === res.module && x.method === res.func.id?.name); if (found) { checked[nodeId] = true; return true; } } if (!res?.func) { checked[nodeId] = false; return false; } if (checked[nodeId] != true) checked[nodeId] = false; const scanRes = scanfunc(res.func, res.context); checked[nodeId] = scanRes; return scanRes; } function scanfunc(node, context) { const throws = exploreChildren(node, (child, parent_, resolve) => { const try_ = findInParent(child, isTryStatement); if (try_) { const catch_ = findInChildren(try_.parent, isCatchClause); const throw_ = catch_ && findInChildren(catch_, isThrowStatement); if (throw_) { resolve(true); } return; } if (isCallExpression(child) && isIdentifier(child.callee)) { let throws = false; if (scannedFunctions.has(getFunctionId(context, child.callee))) { throws = throwFunctions.has(getFunctionId(context, child.callee)); if (throws) resolve(throws); return; } throws = canFuncThrow(child.callee, context); if (throws) { if (node.id) throwFunctions.add(getFunctionId(context, node.id)); resolve(true); } } else if (isThrowStatement(child) && node.id) { throwFunctions.add(getFunctionId(context, node.id)); resolve(true); } }); if (node.id) { scannedFunctions.add(getFunctionId(context, node.id)); if (throws) { throwFunctions.add(getFunctionId(context, node.id)); } } return !!throws; }