tools/core/inspectors/entrypoint.inspector.ts

tools/core/inspectors/entrypoint.inspector.ts is a file in Coordination Surface. 113 lines of code and 39 definitions.

import { braceDelta, memberKey, memberValue } from "../analyzers/source.analyzer.ts";
import type { BranchOperand } from "../types/entrypoint.types.ts";

const DECLARE_CONST = "const ";

const BLOCK_CLOSE = "}";

const BRANCH_MARKS = ["?", "if (", "&&", "||"];

interface ScanState {
    readonly inRun: boolean;
    readonly inReport: boolean;
    readonly runDepth: number;
    readonly reportDepth: number;
}

interface LineFacts {
    readonly line: number;
    readonly branching: string | null;
    readonly passed: string | null;
    readonly published: readonly string[];
}

interface Calls {
    readonly carrier: string;
    readonly runCall: string;
    readonly reportCall: string;
}

const OUTSIDE: ScanState = { inReport: false, inRun: false, reportDepth: 0, runDepth: 0 };

const declaresCarrier = function declaresCarrier(trimmed: string, carrier: string): boolean {
    const lead = `${DECLARE_CONST}${carrier}`;
    if (!trimmed.startsWith(lead)) {
        return false;
    }
    const next = trimmed.charAt(lead.length);
    return next === " " || next === ":" || next === "=";
};

const carrierIn = function carrierIn(line: string, reportCall: string): string {
    const at = line.indexOf(`${reportCall}(`);
    if (at === -1) {
        return "";
    }
    const inside = line.slice(at + reportCall.length + 1);
    const close = inside.indexOf(")");
    return close === -1 ? "" : (inside.slice(0, close).split(",").at(-1) ?? "").trim();
};

const reportCarrier = function reportCarrier(lines: readonly string[], reportCall: string): string {
    return lines.map((line) => carrierIn(line, reportCall)).find((carrier) => carrier.length > 0) ?? "";
};

const branchingName = function branchingName(trimmed: string): string | null {
    if (!trimmed.startsWith(DECLARE_CONST) || !BRANCH_MARKS.some((mark) => trimmed.includes(mark))) {
        return null;
    }
    const rest = trimmed.slice(DECLARE_CONST.length);
    const stop = rest.indexOf(" ");
    return stop <= 0 ? null : rest.slice(0, stop);
};

const opened = function opened(state: ScanState, trimmed: string, calls: Calls): ScanState {
    const declared = calls.carrier.length > 0 && declaresCarrier(trimmed, calls.carrier);
    const opensReport = declared || trimmed.includes(`${calls.reportCall}(`);
    const opensRun = trimmed.includes(`${calls.runCall}(`);
    return {
        inReport: state.inReport || opensReport,
        inRun: state.inRun || opensRun,
        reportDepth: opensReport ? 0 : state.reportDepth,
        runDepth: opensRun ? 0 : state.runDepth,
    };
};

const closed = function closed(state: ScanState, trimmed: string): ScanState {
    const delta = braceDelta(trimmed);
    const runDepth = state.runDepth + (state.inRun ? delta : 0);
    const reportDepth = state.reportDepth + (state.inReport ? delta : 0);
    const closes = trimmed.startsWith(BLOCK_CLOSE);
    return {
        inReport: state.inReport && !(reportDepth <= 0 && closes),
        inRun: state.inRun && !(runDepth <= 0 && closes),
        reportDepth,
        runDepth,
    };
};

const factsOf = function factsOf(state: ScanState, trimmed: string, line: number): LineFacts {
    const value = memberValue(trimmed);
    return {
        branching: branchingName(trimmed),
        line,
        passed: state.inRun && value.length > 0 ? value : null,
        published: state.inReport ? [memberKey(trimmed), value].filter((word) => word.length > 0) : [],
    };
};

const scannedFacts = function scannedFacts(lines: readonly string[], calls: Calls): LineFacts[] {
    const out: LineFacts[] = [];
    let state = OUTSIDE;

    for (const [index, line] of lines.entries()) {
        const trimmed = line.trim();
        state = opened(state, trimmed, calls);
        out.push(factsOf(state, trimmed, index + 1));
        state = closed(state, trimmed);
    }

    return out;
};

export const unpublishedBranchOperands = function unpublishedBranchOperands(
    source: string,
    runCall: string,
    reportCall: string,
): BranchOperand[] {
    const lines = source.split("\n");
    const facts = scannedFacts(lines, { carrier: reportCarrier(lines, reportCall), reportCall, runCall });

    const branching = new Set(facts.flatMap((fact) => (fact.branching === null ? [] : [fact.branching])));
    const published = new Set(facts.flatMap((fact) => fact.published));
    const passed = new Map(
        facts
            .flatMap((fact): [string, number][] => (fact.passed === null ? [] : [[fact.passed, fact.line]]))
            .toReversed(),
    );

    return [...passed]
        .filter(([name]) => branching.has(name) && !published.has(name))
        .toSorted((left, right) => left[1] - right[1])
        .map(([name, line]) => ({ line, name }));
};