import { computeLineHash, escapeControlCharsForDisplay } from "./hashline.js"; export interface PtcLine { line: number; hash: string; anchor: string; raw: string; display: string; } export interface PtcWarningSymbol { name: string; kind: string; startLine: number; endLine: number; parentName?: string; } export interface PtcWarning { code: string; message: string; tier?: "camelCase" | "substring"; symbol?: PtcWarningSymbol; otherCandidates?: PtcWarningSymbol[]; } export interface PtcError { code: string; message: string; hint?: string; details?: unknown; } export interface PtcRange { startLine: number; endLine: number; totalLines?: number; } export interface PtcFileGroup { path: string; ranges: PtcRange[]; lines: PtcLine[]; } export interface SemanticSummary { classification: "no-op" | "whitespace-only" | "semantic" | "mixed"; difftasticAvailable: boolean; movedBlocks?: number; } export interface PtcEditResult { tool: "edit"; ok: boolean; path: string; summary: string; diff: string; firstChangedLine: number | undefined; warnings: string[]; noopEdits: unknown[]; semanticSummary?: SemanticSummary; } export function buildPtcLine(line: number, raw: string): PtcLine { const hash = computeLineHash(line, raw); return { line, hash, anchor: `${line}:${hash}`, raw, display: escapeControlCharsForDisplay(raw), }; } export function buildPtcLines(startLine: number, rawLines: string[]): PtcLine[] { return rawLines.map((raw, index) => buildPtcLine(startLine + index, raw)); } export function renderPtcLine(line: PtcLine): string { return `${line.anchor}|${line.display}`; } export function renderPtcLines(lines: PtcLine[]): string { return lines.map(renderPtcLine).join("\n"); } export function buildPtcWarning( code: string, message: string, metadata: Omit = {}, ): PtcWarning { return { code, message, ...metadata }; } export function buildPtcError( code: string, message: string, hint?: string, details?: unknown, ): PtcError { return { code, message, ...(hint !== undefined ? { hint } : {}), ...(details !== undefined ? { details } : {}), }; } export function buildPtcRange(startLine: number, endLine: number, totalLines?: number): PtcRange { return totalLines === undefined ? { startLine, endLine } : { startLine, endLine, totalLines }; } export function buildPtcFileGroup(path: string, ranges: PtcRange[], lines: PtcLine[]): PtcFileGroup { return { path, ranges: ranges.map((range) => ({ ...range })), lines: lines.map((line) => ({ ...line })), }; } export function buildPtcEditResult(input: { ok?: boolean; path: string; summary: string; diff: string; firstChangedLine: number | undefined; warnings: string[]; noopEdits: unknown[]; semanticSummary?: SemanticSummary; }): PtcEditResult { return { tool: "edit", ok: input.ok ?? true, path: input.path, summary: input.summary, diff: input.diff, firstChangedLine: input.firstChangedLine, warnings: [...input.warnings], noopEdits: [...input.noopEdits], ...(input.semanticSummary ? { semanticSummary: input.semanticSummary } : {}), }; }