/** * Literal reflective dispatch resolution (change: resolve-literal-reflective-dispatch). * * The dynamic-boundary matcher records every reflective construct as a CANDIDATE. This module * decides, after every other edge exists (Pass 7a), which candidates bind structurally. One family is * recovered: a **literal dispatch table** — `HANDLERS[k]()` / `HANDLERS["create"]()` over a * module-private JS/TS `const` table the matcher proved stable in its file. Each entry binds by the * byte span of its same-file module-level declaration, never by name; an entry the matcher could * not prove local (an import, a reassigned or `this`-using function) keeps the construct a site. A * non-literal key binds every entry or none, and a table over the synthesis fan-out cap binds none. * * Deliberately NOT recovered: a literal member on a self-typed receiver (`this["m"]()`, * `getattr(self, "m")()`, Ruby `send(:m)`). Two rounds of adversarial review showed the class graph * cannot bound that type soundly — members added by assignment or mixins, and subclasses whose * parent never resolved, are invisible — so those constructs stay disclosed sites. * * The output is additive: synthesized edges plus the bound and refused candidate keys that decide * the dynamic-boundary partition. Deterministic: inputs in build order, targets in id order. */ import type { CallEdge, FunctionNode } from './call-graph-types.js'; import { type AttributedCandidate, type DynamicBoundaryRefusal } from './dynamic-boundary.js'; export interface LiteralReflectionInput { candidatesByFile: ReadonlyMap; nodes: ReadonlyMap; /** Every edge accumulated so far. An emitted caller→callee pair never duplicates one of these. */ edges: readonly CallEdge[]; /** The synthesis per-site fan-out cap, passed in so this module stays a leaf. */ fanOutCap: number; } export interface LiteralReflectionResult { /** New `literal-reflective` edges, never a pair already present in the input edges. */ edges: CallEdge[]; /** {@link literalReflectionKey} of every candidate whose targets bound (their edges exist). */ bound: Set; /** The resolver's own refusal for a candidate it attempted and declined. */ refusals: Map; } /** * Candidate identity: a resolved edge carries no offset, so retraction keys on the construct. The * offset leads and the path follows a colon, so no path can make two keys collide. */ export declare function literalReflectionKey(filePath: string, startIndex: number): string; export declare function resolveLiteralReflection(input: LiteralReflectionInput): LiteralReflectionResult; //# sourceMappingURL=literal-reflection.d.ts.map