/**
 * 错误处理路径验证器 — 检测 .ts 文件中的错误处理遗漏。
 *
 * 职责：
 * - 检测未处理的 await 调用（不在 try/catch 中）
 * - 检测 .then() 无 .catch() 的 Promise 链
 * - 检测空 error handler（与 lazy_pattern_detector 联合）
 * - 检测声明 throws 的函数调用方未处理
 *
 * 设计决策：
 * - 所有检测基于纯正则，无 AST 依赖
 * - warning 级别为主（不阻断），仅空 error handler 为 hard_fail
 * - 优雅降级：非 .ts 文件返回空数组，不抛异常
 */
// ── 核心检测函数 ──
/**
 * 对 .ts 文件内容执行错误处理路径验证。
 *
 * @param content 文件内容
 * @param filePath 文件路径（用于文件类型判断）
 * @returns 错误处理路径发现项数组
 */
export function verifyErrorHandlingPaths(content, filePath) {
    // 优雅降级：非 .ts 文件返回空数组
    if (!filePath.endsWith(".ts") || filePath.endsWith(".d.ts")) {
        return [];
    }
    const findings = [];
    const lines = content.split("\n");
    // 跟踪 try/catch 嵌套深度（简化版：基于括号计数）
    let tryCatchDepth = 0;
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        const trimmed = line.trim();
        // 跳过纯注释行和空行
        if (!trimmed || /^\s*(?:\/\/|\/\*|\*(?:\/|$))/.test(trimmed))
            continue;
        // 跳过 eslint-disable 行
        if (/eslint-disable/.test(trimmed))
            continue;
        // 跟踪 try/catch 深度
        if (/\btry\s*\{/.test(trimmed))
            tryCatchDepth++;
        if (/\bcatch\s*\(/.test(trimmed))
            tryCatchDepth = Math.max(0, tryCatchDepth - 1);
        // ── 检测 1: 未处理的 await 调用 ──
        const awaitMatch = /^\s*(?:const|let|var)?\s*(?:\w+(?:\.\w+)*\s*=)?\s*await\s+/.exec(trimmed);
        if (awaitMatch && tryCatchDepth === 0) {
            // 排除：顶层 await（模块级）和已有 .catch() 链式调用
            if (!trimmed.includes(".catch(") && !trimmed.includes(").catch(")) {
                const fnName = extractFunctionName(trimmed) || "匿名";
                findings.push({
                    function_name: fnName,
                    line_number: i + 1,
                    issue: "unhandled_await",
                    severity: "warning",
                    message: `await 调用未在 try/catch 中：第 ${i + 1} 行的异步操作缺少错误处理路径`,
                });
            }
            continue; // 同行不重复检测
        }
        // ── 检测 2: .then() 无 .catch() ──
        const thenMatch = /\.then\s*\(/.exec(trimmed);
        if (thenMatch && !trimmed.includes(".catch(") && !trimmed.includes(").catch(")) {
            // 检查下一行是否有 .catch（链式调用可能跨行）
            const nextLine = i + 1 < lines.length ? lines[i + 1].trim() : "";
            if (!nextLine.includes(".catch(")) {
                const fnName = extractFunctionName(trimmed) || "匿名";
                findings.push({
                    function_name: fnName,
                    line_number: i + 1,
                    issue: "unhandled_promise",
                    severity: "warning",
                    message: `.then() 链缺少 .catch()：第 ${i + 1} 行的 Promise 链未处理拒绝情况`,
                });
            }
            continue;
        }
        // ── 检测 3: 空 error handler ──
        const emptyCatchMatch = /catch\s*\(\s*\w+\s*(?::\s*\w+)?\s*\)\s*\{\s*(?:\/\/.*|\/\*.*?\*\/)?\s*\}/.exec(trimmed);
        if (emptyCatchMatch) {
            // 排除有 eslint-disable 注释的行
            if (!/eslint-disable/.test(trimmed)) {
                findings.push({
                    function_name: extractFunctionName(trimmed) || "匿名",
                    line_number: i + 1,
                    issue: "empty_error_handler",
                    severity: "hard_fail",
                    message: `空 catch 块：第 ${i + 1} 行捕获了异常但未做任何处理`,
                });
            }
            continue;
        }
        // ── 检测 4: @throws 声明但调用方未处理 ──
        // 仅做简化检测：查找 @throws 标注的函数名，检查后续调用是否有 try/catch
        const throwsMatch = /@throws\s+(?:\{[^}]+\}\s+)?(?:\w+(?:<[^>]+>)?)\s*[\s-]*(?:当|if|If|如果)?/.exec(trimmed);
        if (throwsMatch) {
            // 提取函数签名中的函数名
            const prevLine = i > 0 ? lines[i - 1].trim() : "";
            const funcNameMatch = /(?:function|const|let)\s+(\w+)/.exec(prevLine);
            if (funcNameMatch) {
                // 标记为需要关注，但不直接报 warning（调用方可能在不同文件）
                // 这里只做注释记录，不生成 finding
            }
        }
    }
    return findings;
}
/**
 * 从代码行中提取函数名（简化版）。
 */
function extractFunctionName(line) {
    // const xxx = ...
    const constMatch = /(?:const|let|var)\s+(\w+)/.exec(line);
    if (constMatch)
        return constMatch[1];
    // function xxx(...)
    const funcMatch = /function\s+(\w+)/.exec(line);
    if (funcMatch)
        return funcMatch[1];
    // xxx.yyy(...)
    const methodMatch = /(\w+)\.(\w+)\s*\(/.exec(line);
    if (methodMatch)
        return `${methodMatch[1]}.${methodMatch[2]}`;
    // xxx(...)
    const callMatch = /(\w+)\s*\(/.exec(line);
    if (callMatch)
        return callMatch[1];
    return "";
}
//# sourceMappingURL=error_path_verifier.js.map