import type { Node } from '@babel/types'; import type { Replacement, SourceRange } from '../seam/types'; import { type LlmCategory } from './classify'; /** * One pre-parsed replacement entry stored in the map. The `node` is a fresh AST * node parsed from `replacement`; the metadata fields travel WITH the entry so * the reporter's id→tag/rationale side-table can be built from the same map. */ export interface ParsedEntry { /** The pre-parsed replacement AST node (a fresh tree, distinct identity). */ node: Node; /** The per-candidate mutator name, e.g. `llm/off-by-one` (from propose.ts). */ mutatorName: string; /** * The `Llm` Stryker mutator this entry is yielded under — chosen * DETERMINISTICALLY from the parsed `(original, replacement)` pair * (`classify.ts`), never from the model's free-text tag. `LlmOther` when * the original does not parse as an expression. */ category: LlmCategory; /** The replacement source text (re-parsed per yield for distinct node identity). */ replacement: string; /** The original span text, carried for the reporter's survivor view. */ original: string; /** Optional LLM rationale, carried for the reporter's survivor view. */ rationale?: string; } /** * The precomputed lookup table the `LLMMutator` reads: outer key = absolute * fileName, inner key = babel-loc key, value = the LIST of candidates at that * span. Two O(1) lookups + an early bail for every non-targeted file/node (the * overwhelmingly common case across a whole-repo instrument). */ export type LlmMutatorMap = Map>; /** * One dropped (non-expression / unparseable) replacement, for logging. The * map-builder drops-and-collects these rather than throwing. */ export interface DroppedReplacement { /** Absolute file the dropped replacement targeted. */ fileName: string; /** The 0-based Stryker range it targeted (for a `file:line` log). */ range: SourceRange; /** The replacement text that failed to parse as an expression. */ replacement: string; /** Why it was dropped. */ reason: string; } /** The result of {@link buildLlmMutatorMap}: the map plus the dropped log. */ export interface BuildLlmMutatorMapResult { /** The precomputed `(absFileName, locKey) → ParsedEntry[]` map. */ map: LlmMutatorMap; /** Replacements dropped because they did not parse as an expression. */ dropped: DroppedReplacement[]; } /** * Build the babel-loc key from a Stryker 0-based {@link SourceRange}, applying * the worker's `+1` line conversion (columns unchanged). This is the BUILD half * of the keying contract — `instrument-worker.mjs` line 106 verbatim. */ export declare function locKeyFromRange(range: SourceRange): string; /** * A babel `loc` shape (1-based line, 0-based column) — the structural slice the * `LLMMutator` reads off `path.node.loc`. */ export interface BabelLoc { start: { line: number; column: number; }; end: { line: number; column: number; }; } /** * Build the lookup key from a live babel `node.loc` (already 1-based line) with * NO offset. This is the READ half of the keying contract — `instrument-worker.mjs` * line 118 verbatim. Pairs with {@link locKeyFromRange}: a 0-based range at line * L keys to `L+1`, and a babel loc at line `L+1` reads to the SAME `L+1`. */ export declare function locKeyFromBabelLoc(loc: BabelLoc): string; /** * Build the precomputed `LLMMutator` map from the FILTERED survivor * replacements. Each survivor is pre-parsed (parens-wrap, expression-only) and * entered under its absolute fileName + babel-loc key; a replacement that fails * to parse as an expression is dropped-and-collected (NOT thrown). * * @param survivors The filtered `Replacement[]` (post `applyFilters` + near-equiv). * @param cwd Base dir for resolving non-absolute `fileName`s to the absolute * path Stryker keys by. Defaults to `process.cwd()`. * @returns The map and the dropped-replacement log. */ export declare function buildLlmMutatorMap(survivors: readonly Replacement[], cwd?: string): BuildLlmMutatorMapResult; /** * Count the map's entries per `Llm` (names with zero entries are * absent). Used for the pre-pass log line and the per-category summary. */ export declare function countEntriesByCategory(map: LlmMutatorMap): ReadonlyMap;