// Planu — LCOM-lite cohesion metric (SPEC-482)
// Approximates Lack of Cohesion of Methods: low LCOM → high cohesion.
import { readFileSync } from 'node:fs';
/** Extract function/method names from a file source. */
function extractFunctionNames(source) {
    const names = [];
    const re = /(?:function\s+(\w+)|(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?(?:\([^)]*\)|[\w]+)\s*=>)/g;
    let m;
    while ((m = re.exec(source)) !== null) {
        const name = m[1] ?? m[2];
        if (name !== undefined && name.length > 0) {
            names.push(name);
        }
    }
    return names;
}
/** Extract top-level const/let/var variable names (shared state candidates). */
function extractTopLevelVars(source) {
    const vars = [];
    const re = /^(?:const|let|var)\s+(\w+)/gm;
    let m;
    while ((m = re.exec(source)) !== null) {
        if (m[1] !== undefined) {
            vars.push(m[1]);
        }
    }
    return vars;
}
/**
 * Compute a cohesion score 0-1 via LCOM-lite.
 * For each shared variable, count how many functions reference it.
 * cohesion = avg(references / functionCount), clamped to [0,1].
 * A score of 1 means all functions share all variables (highly cohesive).
 */
export function computeCohesion(filePath) {
    let source;
    try {
        source = readFileSync(filePath, 'utf8');
    }
    catch {
        return 0.5; // neutral if unreadable
    }
    const functions = extractFunctionNames(source);
    const vars = extractTopLevelVars(source);
    if (functions.length === 0 || vars.length === 0) {
        return 1;
    } // trivial file → fully cohesive
    // For each var, count how many function bodies reference it
    const fnRe = /function\s+\w+\s*\([^)]*\)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/g;
    const fnBodies = [];
    let fm;
    while ((fm = fnRe.exec(source)) !== null) {
        if (fm[1] !== undefined) {
            fnBodies.push(fm[1]);
        }
    }
    if (fnBodies.length === 0) {
        return 0.7;
    } // no parseable bodies
    let totalRatio = 0;
    for (const v of vars) {
        const refsCount = fnBodies.filter((body) => body.includes(v)).length;
        totalRatio += refsCount / fnBodies.length;
    }
    const cohesion = totalRatio / vars.length;
    return Math.min(1, Math.max(0, cohesion));
}
//# sourceMappingURL=cohesion.js.map