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 }));
};