/**
 * 源码结构化匹配工具 — 替代 release_readiness_gate.ts 中的脆弱 .includes() 调用。
 *
 * 解决的问题:
 * - .includes() 不区分生产代码和注释/测试代码
 * - 空格或格式变更会破坏检查
 * - 无法处理不同的引号风格和 import 写法
 */
// ── 注释剥离 ──
/**
 * 剥离 TypeScript 源码中的注释（单行 + 多行 + JSDoc）。
 * 保留字符串字面量内容不变。
 */
export function stripComments(source) {
    // 简单状态机：跟踪是否在字符串字面量中
    let result = "";
    let i = 0;
    let inString = null;
    let inTemplateExpr = 0;
    while (i < source.length) {
        const ch = source[i];
        const next = source[i + 1];
        // 字符串字面量内
        if (inString) {
            result += ch;
            if (ch === "\\") {
                // 转义字符，跳过下一个
                result += source[++i] ?? "";
            }
            else if (inString === "`" && ch === "$" && next === "{") {
                inTemplateExpr++;
                result += next;
                i += 2;
                continue;
            }
            else if (inString === "`" && ch === "}" && inTemplateExpr > 0) {
                inTemplateExpr--;
                result += ch;
            }
            else if (ch === inString && inTemplateExpr === 0) {
                inString = null;
            }
            i++;
            continue;
        }
        // 进入字符串字面量
        if (ch === "'" || ch === '"' || ch === "`") {
            inString = ch;
            result += ch;
            i++;
            continue;
        }
        // 单行注释
        if (ch === "/" && next === "/") {
            const eol = source.indexOf("\n", i);
            i = eol === -1 ? source.length : eol;
            continue;
        }
        // 多行/JSDoc 注释
        if (ch === "/" && next === "*") {
            const end = source.indexOf("*/", i + 2);
            i = end === -1 ? source.length : end + 2;
            continue;
        }
        result += ch;
        i++;
    }
    return result;
}
// ── 标准化匹配 ──
/**
 * 标准化源码用于匹配：移除多余空白，保留结构。
 */
export function normalizeForMatch(source) {
    return source.replace(/\s+/g, " ").trim();
}
/**
 * 检查源码是否包含指定标识符（单词边界匹配）。
 * 自动剥离注释后匹配。
 */
export function sourceContainsIdentifier(source, identifier) {
    const clean = stripComments(source);
    const pattern = new RegExp(`\\b${escapeRegex(identifier)}\\b`);
    return pattern.test(clean);
}
/**
 * 检查源码是否包含 import 语句引入指定模块。
 * 处理静态 import 和 dynamic import，兼容不同引号风格。
 */
export function sourceImportsModule(source, moduleName) {
    const clean = stripComments(source);
    // 导入语句匹配：import ... from "module" | import("module") | require("module")
    const escaped = escapeRegex(moduleName);
    const patterns = [
        new RegExp(`import\\s+.*?from\\s+['"\`]${escaped}['"\`]`),
        new RegExp(`import\\s*\\(\\s*['"\`]${escaped}['"\`]\\s*\\)`),
        new RegExp(`require\\s*\\(\\s*['"\`]${escaped}['"\`]\\s*\\)`),
    ];
    return patterns.some((p) => p.test(clean));
}
/**
 * 检查源码是否包含指定函数调用模式（空白不敏感）。
 * 例: sourceContainsCall(src, "validateStateFactPartition")
 */
export function sourceContainsCall(source, functionName) {
    const clean = stripComments(source);
    const normalized = normalizeForMatch(clean);
    const escaped = escapeRegex(functionName);
    return new RegExp(`${escaped}\\s*\\(`).test(normalized);
}
/**
 * 检查源码是否包含 Zod schema 定义模式。
 * 例: sourceContainsZodSchema(src, "decision_workshop", "z.unknown()")
 * 空白不敏感。
 */
export function sourceContainsZodSchema(source, fieldName, schemaPattern) {
    const clean = stripComments(source);
    const normalized = normalizeForMatch(clean);
    const escapedField = escapeRegex(fieldName);
    // 对 schema pattern：在每个字符间插入 \s* 以容忍任意空白
    const nonSpaceChars = [...schemaPattern].filter((ch) => !/\s/.test(ch));
    const escapedParts = nonSpaceChars.map((ch) => escapeRegex(ch));
    const schemaRegex = escapedParts.join("\\s*");
    return new RegExp(`${escapedField}\\s*:\\s*${schemaRegex}`).test(normalized);
}
/**
 * 检查源码是否包含任意一个给定的字符串模式（空白不敏感，注释安全）。
 */
export function sourceContainsAny(source, patterns) {
    return patterns.some((p) => sourceContainsPattern(source, p));
}
/**
 * 检查源码是否包含指定字符串模式（空白不敏感，注释安全）。
 */
export function sourceContainsPattern(source, pattern) {
    const clean = stripComments(source);
    const normalized = normalizeForMatch(clean);
    const escaped = escapeRegex(pattern).replace(/\s+/g, "\\s+");
    return new RegExp(escaped).test(normalized);
}
/**
 * 检查源码是否包含属性赋值模式。
 * 例: sourceContainsPropertyAccess(src, "ctx", "decision_workshop")
 * 匹配: ctx.decision_workshop, (ctx as any).decision_workshop, (params.ctx as any).decision_workshop
 */
export function sourceContainsPropertyAccess(source, objectName, propertyName) {
    const clean = stripComments(source);
    const escapedObj = escapeRegex(objectName);
    const escapedProp = escapeRegex(propertyName);
    // 三种模式：obj.prop, (obj as X).prop, (Y.obj as X).prop
    const patterns = [
        // 直接访问: ctx.field
        new RegExp(`\\b${escapedObj}\\s*\\.\\s*${escapedProp}\\b`),
        // 带类型断言: (ctx as any).field 或 (ctx as Record<string, unknown>).field
        new RegExp(`\\(\\s*${escapedObj}\\s+as\\s+\\w+(?:<[^>]+>)?\\s*\\)\\s*\\.\\s*${escapedProp}`),
        // 带命名空间断言: (params.ctx as any).field
        new RegExp(`\\(\\s*\\w+\\s*\\.\\s*${escapedObj}\\s+as\\s+\\w+(?:<[^>]+>)?\\s*\\)\\s*\\.\\s*${escapedProp}`),
    ];
    return patterns.some((p) => p.test(clean));
}
// ── 工具函数 ──
function escapeRegex(str) {
    return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
//# sourceMappingURL=source_code_matcher.js.map