@workos/oagen 0.24.0 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"diff-B7dMUCoJ.mjs","names":["extractDeclarationName","declarationKey","path","path","path"],"sources":["../src/ir/operation-hints.ts","../src/engine/merge-adapters/url-fingerprint.ts","../src/engine/merge-adapters/dotnet.ts","../src/engine/merge-adapters/elixir.ts","../src/engine/merge-adapters/go.ts","../src/engine/merge-adapters/kotlin.ts","../src/engine/merge-adapters/node.ts","../src/engine/merge-adapters/php.ts","../src/engine/merge-adapters/python.ts","../src/engine/merge-adapters/ruby.ts","../src/engine/merge-adapters/rust.ts","../src/engine/merge-adapters/index.ts","../src/engine/merger.ts","../src/engine/json-merge.ts","../src/engine/writer.ts","../src/engine/generate-files.ts","../src/engine/scoped-services.ts","../src/engine/integrate.ts","../src/engine/formatter.ts","../src/engine/manifest.ts","../src/engine/orchestrator.ts","../src/engine/registry.ts","../src/differ/classify.ts","../src/differ/models.ts","../src/differ/operations.ts","../src/differ/services.ts","../src/differ/diff.ts"],"sourcesContent":["import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n return s\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[-\\s.]+/g, '_')\n .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /auth/token\"). */\nexport interface OperationHint {\n /** Override the algorithm-derived method name. */\n name?: string;\n /** Remount this operation to a different service/namespace (PascalCase). */\n mountOn?: string;\n /** Split a union-body operation into N typed wrapper methods. */\n split?: SplitHint[];\n /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n inferFromClient?: string[];\n /**\n * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n * should generate a method that returns the constructed URL (typically as a\n * string) without performing any I/O. Used for OAuth-style redirect endpoints\n * such as /auth/authorize and /accounts/sessions/logout.\n */\n urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n targetVariant: string;\n /** Constant body fields injected by the wrapper. */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime. */\n inferFromClient?: string[];\n /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n exposedParams?: string[];\n /**\n * Subset of exposedParams that should be emitted as optional even when the\n * variant model would otherwise mark them required (or when the variant has\n * no addressable model, as happens for inline oneOf branches).\n */\n optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n /** The original IR operation (preserves description, params, types, etc.). */\n operation: Operation;\n /** The original IR service that owns this operation. */\n service: Service;\n /** Resolved snake_case method name (emitters convert to their convention). */\n methodName: string;\n /** Resolved target service/namespace (PascalCase). */\n mountOn: string;\n /** For split operations: one wrapper per union variant. */\n wrappers?: ResolvedWrapper[];\n /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n defaults: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n inferFromClient: string[];\n /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name. */\n targetVariant: string;\n /** Constant body defaults injected by the wrapper. */\n defaults: Record<string, string | number | boolean>;\n /** Fields read from client config at runtime. */\n inferFromClient: string[];\n /** Body fields exposed as method params. */\n exposedParams: string[];\n /** Optional body fields (not required in the variant). */\n optionalParams: string[];\n /** Response model name (if any). */\n responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n 'accept',\n 'activate',\n 'authorize',\n 'challenge',\n 'check',\n 'complete',\n 'confirm',\n 'deactivate',\n 'disable',\n 'enable',\n 'enroll',\n 'generate',\n 'reactivate',\n 'resend',\n 'revoke',\n 'send',\n 'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n get: 'list',\n post: 'create',\n put: 'update',\n patch: 'update',\n delete: 'delete',\n head: 'get',\n options: 'list',\n trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n if (word.length <= 2) return word;\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n if (\n word.endsWith('ses') ||\n word.endsWith('zes') ||\n word.endsWith('xes') ||\n word.endsWith('ches') ||\n word.endsWith('shes')\n ) {\n return word.slice(0, -2);\n }\n if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n if (word.endsWith('s')) return word.slice(0, -1);\n return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n const segments = op.path.split('/').filter(Boolean);\n\n // Separate static segments from param segments\n const staticSegments: string[] = [];\n let trailingParam = false;\n for (const seg of segments) {\n if (seg.startsWith('{') && seg.endsWith('}')) {\n trailingParam = true;\n } else {\n staticSegments.push(seg);\n trailingParam = false;\n }\n }\n\n if (staticSegments.length === 0) {\n return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n }\n\n const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n // Check if terminal is an action verb\n if (ACTION_VERBS.has(terminal)) {\n // Resource context from preceding segments\n const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n if (resource) {\n return `${terminal}_${resource}`;\n }\n return terminal;\n }\n\n // Determine verb from HTTP method\n let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n // GET with trailing {id} → \"get\" instead of \"list\"\n if (op.httpMethod === 'get' && trailingParam) {\n verb = 'get';\n }\n\n // Build resource name from static segments.\n // When path params separate static segments, include the penultimate static\n // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n // e.g. /projects/{id}/roles → \"project_roles\"\n let resource = toSnake(terminal);\n if (staticSegments.length >= 2) {\n const penultimate = staticSegments[staticSegments.length - 2];\n // Check if a path param appears between the penultimate and terminal segments\n // in the original path by finding both positions and looking for {…} between them.\n const penIdx = segments.lastIndexOf(penultimate);\n const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n if (hasParamBetween) {\n const prefix = toSnake(singularize(penultimate));\n resource = `${prefix}_${resource}`;\n }\n }\n\n // Singularize when:\n // * there's a trailing path param (single-resource read/update/delete), or\n // * the verb itself implies a single-resource operation (e.g. POST → create\n // always creates one item even when posted to a collection endpoint).\n const isSingleResource = trailingParam || verb === 'create';\n const noun = isSingleResource ? singularize(resource) : resource;\n\n // For \"list\" verb, keep plural\n const finalNoun = verb === 'list' ? resource : noun;\n\n return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n spec: ApiSpec,\n hints?: Record<string, OperationHint>,\n mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n const resolved: ResolvedOperation[] = [];\n const hintMap = hints ?? {};\n const mounts = mountRules ?? {};\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const hint = hintMap[key];\n\n // Resolve method name: hint > algorithm\n const methodName = hint?.name ?? deriveMethodName(op, service);\n\n // Resolve mount target: per-op hint > service mount rule > original service\n const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n // Build wrappers for split operations\n let wrappers: ResolvedWrapper[] | undefined;\n if (hint?.split) {\n wrappers = hint.split.map((sh) => ({\n name: sh.name,\n targetVariant: sh.targetVariant,\n defaults: sh.defaults ?? {},\n inferFromClient: sh.inferFromClient ?? [],\n exposedParams: sh.exposedParams ?? [],\n optionalParams: sh.optionalParams ?? [],\n responseModelName: resolveResponseModelName(op),\n }));\n }\n\n resolved.push({\n operation: op,\n service,\n methodName,\n mountOn,\n wrappers,\n defaults: hint?.defaults ?? {},\n inferFromClient: hint?.inferFromClient ?? [],\n urlBuilder: hint?.urlBuilder ?? false,\n });\n }\n }\n\n return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n if (op.httpMethod === 'delete') return null;\n const ref = op.response;\n if (ref.kind === 'model') return ref.name;\n if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n return null;\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n const stringTypes = new Set(config.stringNodeTypes);\n const contentTypes = new Set(config.contentNodeTypes);\n const interpolationTypes = new Set(config.interpolationNodeTypes);\n const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n // Iterative DFS through the method's AST subtree\n const stack: Parser.SyntaxNode[] = [memberNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (stringTypes.has(node.type)) {\n const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // For format functions (Go's Sprintf, Rust's format!): check if this call\n // matches and extract the first string argument.\n if (formatFns && isFormatCall(node, formatFns)) {\n const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // Push children in reverse order so leftmost child is processed first\n for (let i = node.childCount - 1; i >= 0; i--) {\n const child = node.child(i);\n if (child) stack.push(child);\n }\n }\n\n return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n stringNode: Parser.SyntaxNode,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n // Leaf string node (no children besides quotes) — strip quotes\n if (stringNode.namedChildCount === 0) {\n return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n }\n\n // Composite string (has content fragments + interpolation children)\n let result = '';\n for (let i = 0; i < stringNode.childCount; i++) {\n const child = stringNode.child(i)!;\n if (contentTypes.has(child.type)) {\n result += child.text;\n } else if (interpolationTypes.has(child.type)) {\n result += '{}';\n }\n // Skip quote delimiters, interpolation markers, etc.\n }\n\n return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n if (node.type === 'macro_invocation') {\n const macroName = node.childForFieldName('macro')?.text;\n return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n }\n\n if (node.type !== 'call_expression') return false;\n const fnNode = node.childForFieldName('function');\n if (!fnNode) return false;\n\n // Direct call: Sprintf(...) or format!(...)\n if (formatFns.has(fnNode.text)) return true;\n\n // Member call: fmt.Sprintf(...)\n if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n if (prop && formatFns.has(prop.text)) return true;\n }\n return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n callNode: Parser.SyntaxNode,\n stringTypes: Set<string>,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n const args = callNode.childForFieldName('arguments');\n if (!args) return undefined;\n\n for (let i = 0; i < args.childCount; i++) {\n const arg = args.child(i)!;\n if (stringTypes.has(arg.type)) {\n return resolveFingerprint(arg, contentTypes, interpolationTypes);\n }\n }\n return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n contentNodeTypes: ['string_content', 'string_literal_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n 'class_declaration',\n 'struct_declaration',\n 'interface_declaration',\n 'enum_declaration',\n 'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (DECLARATION_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n const nameNode =\n node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode ? `__namespace:${nameNode.text}` : null;\n }\n return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n children: Parser.SyntaxNode[],\n source: string,\n statements: MergeStatement[],\n imports: MergeImport[],\n importAnchors: string[],\n importInsertionAnchor: { value?: string },\n): void {\n for (const child of children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'using_directive') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n if (child.type === 'file_scoped_namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // File-scoped namespace: subsequent declarations are siblings at root\n continue;\n }\n\n if (child.type === 'namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // Block namespace: recurse into declaration_list\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n language: 'dotnet',\n grammarModule: 'tree-sitter-c-sharp',\n testFilePatterns: [/Tests?\\.cs$/],\n urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n const importInsertionAnchor: { value?: string } = {};\n\n collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n return {\n imports,\n importAnchors,\n importInsertionAnchor: importInsertionAnchor.value,\n statements,\n };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n\n function processChildren(children: Parser.SyntaxNode[]): void {\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Recurse into namespaces\n if (child.type === 'namespace_declaration') {\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) processChildren(body.children);\n continue;\n }\n\n const name = extractDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = collectPrecedingXmlDocComments(children, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n // For methods, the second identifier is the name (first is return type)\n const identifiers = member.children.filter((c) => c.type === 'identifier');\n const memberName =\n member.type === 'method_declaration'\n ? identifiers.length >= 2\n ? identifiers[1]!.text\n : identifiers[0]?.text\n : identifiers[0]?.text;\n if (!memberName) continue;\n const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n }\n\n processChildren(tree.rootNode.children);\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['quoted_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n if (!isDefmodule(node)) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n const alias = args.children.find((c) => c.type === 'alias');\n return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'unary_operator') return null;\n const call = node.children.find((c) => c.type === 'call');\n if (!call) return null;\n const id = call.children.find((c) => c.type === 'identifier');\n if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'call') return null;\n const id = node.children[0];\n if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n // The function name is either a simple identifier or a call (for functions with params)\n for (const arg of args.namedChildren) {\n if (arg.type === 'identifier') return arg.text;\n if (arg.type === 'call') {\n const nameNode = arg.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n }\n return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const id = node.children[0];\n return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n language: 'elixir',\n grammarModule: 'tree-sitter-elixir',\n testFilePatterns: [/_test\\.exs$/],\n urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n // Top-level alias/import/require/use (rare but possible outside modules)\n if (isImportLike(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const moduleName = getModuleName(child);\n statements.push({\n key: moduleName,\n kind: moduleName ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const moduleName = getModuleName(child);\n if (!moduleName) continue;\n\n // Look for @moduledoc inside the do_block\n let docstring: DocstringInfo | null = null;\n const doBlock = getDoBlock(child);\n const members = new Map<string, MemberDocstrings>();\n\n if (doBlock) {\n const bodyChildren = doBlock.children;\n\n // Find @moduledoc\n for (const bodyChild of bodyChildren) {\n if (isDocAttribute(bodyChild) === 'moduledoc') {\n docstring = {\n text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n startIndex: bodyChild.startIndex,\n endIndex: bodyChild.endIndex,\n };\n break;\n }\n }\n\n // Find @doc + def pairs for member docstrings\n for (let j = 0; j < bodyChildren.length; j++) {\n const bodyChild = bodyChildren[j];\n const defName = getDefName(bodyChild);\n if (!defName) continue;\n\n // Look for preceding @doc attribute\n let memberDoc: DocstringInfo | null = null;\n for (let k = j - 1; k >= 0; k--) {\n const prev = bodyChildren[k];\n if (isDocAttribute(prev) === 'doc') {\n memberDoc = {\n text: source.slice(prev.startIndex, prev.endIndex),\n startIndex: prev.startIndex,\n endIndex: prev.endIndex,\n };\n break;\n }\n if (prev.type === 'comment') continue;\n break;\n }\n\n members.set(defName, {\n docstring: memberDoc,\n declStartIndex: bodyChild.startIndex,\n declColumn: bodyChild.startPosition.column,\n urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(moduleName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['interpreted_string_literal'],\n contentNodeTypes: ['interpreted_string_literal_content'],\n interpolationNodeTypes: [],\n formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n const receiver = node.childForFieldName('receiver');\n if (!receiver) return null;\n return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'package_clause': {\n const pkg = lastIdentifier(node.text);\n return pkg ? `__package:${pkg}` : '__package:';\n }\n case 'type_declaration': {\n const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n const nameNode = spec?.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'function_declaration': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'method_declaration': {\n const name = node.childForFieldName('name')?.text ?? null;\n const receiver = receiverKey(node);\n return name && receiver ? `method:${receiver}.${name}` : name;\n }\n case 'const_declaration':\n case 'var_declaration': {\n return node.text.split(/\\s+/).slice(0, 3).join(' ');\n }\n default:\n return null;\n }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n const entries: MergeImport[] = [];\n\n const collect = (spec: Parser.SyntaxNode): void => {\n const path = spec.childForFieldName('path')?.text ?? spec.text;\n const name = spec.childForFieldName('name')?.text ?? '';\n const text = source.slice(spec.startIndex, spec.endIndex);\n entries.push({\n key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n text,\n });\n };\n\n for (const child of node.namedChildren) {\n if (child.type === 'import_spec') {\n collect(child);\n continue;\n }\n if (child.type === 'import_spec_list') {\n for (const spec of child.namedChildren) {\n if (spec.type === 'import_spec') collect(spec);\n }\n }\n }\n\n return entries;\n}\n\nfunction collectPrecedingGoComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('//')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n language: 'go',\n grammarModule: 'tree-sitter-go',\n testFilePatterns: [/_test\\.go$/],\n urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'package_clause') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'import_declaration') {\n imports.push(...importEntries(child, source));\n importAnchors.push(source.slice(child.startIndex, child.endIndex));\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n if (imports.length === 0) return [];\n if (imports.length === 1) return [`import ${imports[0]!.text}`];\n return [`import (\\n${imports.map((entry) => ` ${entry.text}`).join('\\n')}\\n)`];\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key || key.startsWith('__package:')) continue;\n\n const docstring = collectPrecedingGoComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n MergeMember,\n DeepMergeSymbol,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_declaration') {\n // Handles class, data class, enum class, etc.\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'function_declaration') {\n const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'object_declaration') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'type_alias') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'property_declaration') {\n const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n if (nameNode) {\n const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n return id?.text ?? null;\n }\n }\n return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === 'line_comment') continue;\n return null;\n }\n return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n const children = classBody.namedChildren;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n let memberName: string | null = null;\n\n if (child.type === 'property_declaration') {\n const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'function_declaration') {\n memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'companion_object') {\n memberName = 'companion';\n }\n\n if (!memberName) continue;\n\n // Fold trailing getter/setter into the property's text span\n let endIdx = child.endIndex;\n if (child.type === 'property_declaration') {\n while (i + 1 < children.length) {\n const next = children[i + 1];\n if (next.type === 'getter' || next.type === 'setter') {\n endIdx = next.endIndex;\n i++;\n } else {\n break;\n }\n }\n }\n\n // Include preceding KDoc comment in the text span so deep merge\n // inserts the member with its documentation intact.\n let startIdx = child.startIndex;\n for (let k = i - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) startIdx = prev.startIndex;\n break;\n }\n if (prev.type === 'line_comment') continue;\n break;\n }\n\n members.push({ key: memberName, text: source.slice(startIdx, endIdx), startIndex: startIdx, endIndex: endIdx });\n }\n\n return members;\n}\n\n/**\n * KDoc signature that identifies a generator-emitted service accessor inside\n * a Kotlin client class. The Kotlin client emitter writes every accessor with this\n * exact doc preamble — when the existing file carries a member with this doc\n * but the regenerated content omits it, the member is stale (its mount target\n * was remapped or removed) and gets pruned.\n */\nconst KOTLIN_MANAGED_ACCESSOR_DOC =\n /\\/\\*\\*[\\s\\S]*?Lazily-constructed \\[[^\\]]+\\] accessor for this \\[[^\\]]+\\] client\\.[\\s\\S]*?\\*\\//;\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n language: 'kotlin',\n grammarModule: 'tree-sitter-kotlin',\n testFilePatterns: [/Test\\.kt$/],\n urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n if (child.type === 'import_list') {\n const fullText = source.slice(child.startIndex, child.endIndex);\n importAnchors.push(fullText);\n for (const imp of child.namedChildren) {\n if (imp.type === 'import_header') {\n const text = source.slice(imp.startIndex, imp.endIndex).trim();\n // Key on the full import path\n const idNode = imp.children.find((c) => c.type === 'identifier');\n const key = idNode?.text ?? text;\n imports.push({ key, text });\n }\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n isManagedMember(member) {\n return KOTLIN_MANAGED_ACCESSOR_DOC.test(member.text);\n },\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // Skip if new members reference instance properties that don't exist in the target\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) return true;\n }\n return false;\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'class_declaration') continue;\n const nameNode = child.children.find((c) => c.type === 'type_identifier');\n if (!nameNode) continue;\n const body = child.children.find((c) => c.type === 'class_body');\n if (!body) continue;\n\n const members = extractKotlinClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractDeclarationName(child);\n if (!name) continue;\n\n const docstring = findPrecedingKdoc(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings for classes\n if (child.type === 'class_declaration') {\n const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n const memberName = extractDeclarationName(member);\n if (!memberName) continue;\n const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DeepMergeSymbol,\n MergeMember,\n DocstringInfo,\n SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode.text;\n\n if (node.type === 'lexical_declaration') {\n const declarator = node.firstNamedChild;\n if (declarator?.type === 'variable_declarator') {\n const name = declarator.childForFieldName('name');\n if (name) return name.text;\n }\n }\n\n return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n if (node.type === 'export_statement') {\n const decl = node.childForFieldName('declaration');\n if (decl) {\n return { key: extractDeclName(decl), kind: 'declaration' };\n }\n\n const source = node.childForFieldName('source');\n if (source) {\n return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n }\n\n return { key: null, kind: 'other' };\n }\n return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of classBody.namedChildren) {\n if (child.type === 'method_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode && nameNode.text !== 'constructor') {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'public_field_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n // tree-sitter may exclude the trailing semicolon from\n // public_field_definition nodes — include it if present\n let endIdx = child.endIndex;\n if (source[endIdx] === ';') {\n endIdx += 1;\n }\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n }\n }\n }\n return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'property_signature' || child.type === 'method_signature') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n }\n return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'enum_assignment') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'property_identifier') {\n members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n // tree-sitter extras (comments) may report the parent node's type\n // instead of 'comment' — check grammarType as fallback\n return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (isCommentNode(prev)) {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string', 'template_string'],\n contentNodeTypes: ['string_fragment'],\n interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n body: Parser.SyntaxNode,\n source: string,\n memberTypes: Set<string>,\n): Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n const result = new Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n >();\n const allChildren = body.children;\n for (let i = 0; i < allChildren.length; i++) {\n const child = allChildren[i];\n if (!memberTypes.has(child.type)) continue;\n let memberName: string | null = null;\n if (child.type === 'property_identifier') {\n memberName = child.text;\n } else {\n const nameNode = child.childForFieldName('name');\n if (nameNode) memberName = nameNode.text;\n }\n if (!memberName || memberName === 'constructor') continue;\n const docstring = findPrecedingDocstring(allChildren, i, source);\n const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n result.set(memberName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n urlFingerprint: fp,\n });\n }\n return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n language: 'node',\n grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n normalizeReexport: normalizeJsExtension,\n testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // If new members reference instance properties (this.X) that don't exist\n // in the target class, the merged code would be broken.\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) {\n return true;\n }\n }\n return false;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n // Key on module path so `import { X }` and `import type { X }` from\n // the same module are treated as duplicates\n const sourceNode = child.childForFieldName('source');\n const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n imports.push({ key: modulePath, text });\n importAnchors.push(text);\n continue;\n }\n\n const { key, kind } = extractNodeKey(child);\n statements.push({\n key,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n const symbolName = nameNode.text;\n\n if (decl.type === 'class_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'interface_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractInterfaceMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'enum_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractEnumMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n\n // Find preceding JSDoc for this top-level symbol\n const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n // Extract member-level docstrings\n let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n const body = decl.childForFieldName('body');\n if (body) {\n if (decl.type === 'class_declaration') {\n members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n } else if (decl.type === 'interface_declaration') {\n members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n } else if (decl.type === 'enum_declaration') {\n members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n }\n }\n\n result.set(nameNode.text, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['encapsed_string', 'string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'class_declaration':\n case 'interface_declaration':\n case 'trait_declaration':\n case 'enum_declaration':\n case 'function_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'namespace_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n }\n default:\n return null;\n }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n language: 'php',\n grammarModule: 'tree-sitter-php',\n testFilePatterns: [/Test\\.php$/],\n urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n resolveGrammar: (mod) => {\n // ESM import wraps in { default: { php, php_only } }\n const m = (mod as Record<string, unknown>)?.default ?? mod;\n if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n return (m as { php: unknown }).php;\n return m;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'namespace_definition') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'namespace_use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPhpDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPhpDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = findPhpDocstring(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n const body = child.childForFieldName('body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n const memberDoc = findPhpDocstring(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_definition' || node.type === 'function_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n\n // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n if (node.type === 'expression_statement') {\n const firstChild = node.firstNamedChild;\n if (firstChild?.type === 'assignment') {\n const left = firstChild.childForFieldName('left');\n if (left?.type === 'identifier' && left.text === '__all__') {\n return '__all__';\n }\n }\n }\n\n return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n // Python docstrings are the first expression_statement in a body block\n // where the expression is a string literal\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'expression_statement') {\n const expr = child.firstNamedChild;\n if (expr?.type === 'string') {\n const text = source.slice(child.startIndex, child.endIndex);\n return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n }\n }\n // Only the FIRST statement can be a docstring\n break;\n }\n return null;\n}\n\nfunction collectPrecedingPythonComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n language: 'python',\n grammarModule: 'tree-sitter-python',\n testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPythonDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPythonDeclarationName(child);\n if (!name) continue;\n\n // Python: class/function docstrings are inside the body, OR use # comments before\n let docstring: DocstringInfo | null = null;\n const body = child.childForFieldName('body');\n if (body) {\n docstring = extractPythonDocstring(body, source);\n }\n // Fallback: check for # comments before the declaration\n if (!docstring) {\n docstring = collectPrecedingPythonComments(rootChildren, i, source);\n }\n\n const members = new Map<string, MemberDocstrings>();\n\n // Extract method docstrings for classes\n if (child.type === 'class_definition' && body) {\n for (const member of body.namedChildren) {\n if (member.type !== 'function_definition') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null = null;\n const memberBody = member.childForFieldName('body');\n if (memberBody) {\n memberDoc = extractPythonDocstring(memberBody, source);\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const method = node.childForFieldName('method');\n if (!method) return false;\n return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'class' && node.type !== 'module') return null;\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n const nodeType = (prev as any).grammarType ?? prev.type;\n if (nodeType === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('#')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n language: 'ruby',\n grammarModule: 'tree-sitter-ruby',\n testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n const declarationName = extractRubyDeclarationName(child);\n if (isRequireCall(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractRubyDeclarationName(child);\n if (!name) continue;\n\n const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Ruby class/module bodies: comments may appear in class children\n // (before body_statement) or in body_statement children (between methods)\n if (child.type === 'class' || child.type === 'module') {\n const allClassChildren = child.children;\n const body = child.childForFieldName('body');\n\n // Check for comment before body_statement in class children\n // (docstring for the first method)\n let firstMethodDocFromClass: DocstringInfo | null = null;\n for (let j = 0; j < allClassChildren.length; j++) {\n if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n break;\n }\n }\n\n if (body) {\n const bodyChildren = body.children;\n let firstMethodHandled = false;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null;\n if (!firstMethodHandled && firstMethodDocFromClass) {\n memberDoc = firstMethodDocFromClass;\n firstMethodHandled = true;\n } else {\n memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n firstMethodHandled = true;\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'struct_item':\n case 'enum_item':\n case 'function_item':\n case 'trait_item':\n case 'type_item':\n case 'const_item': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'impl_item': {\n const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n const traitName = node.childForFieldName('trait')?.text;\n return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n }\n default:\n return null;\n }\n}\n\nfunction collectPrecedingRustDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'line_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n language: 'rust',\n grammarModule: 'tree-sitter-rust',\n testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key) continue;\n\n const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n ['dotnet', dotnetMergeAdapter],\n ['elixir', elixirMergeAdapter],\n ['go', goMergeAdapter],\n ['kotlin', kotlinMergeAdapter],\n ['node', nodeMergeAdapter],\n ['php', phpMergeAdapter],\n ['python', pythonMergeAdapter],\n ['ruby', rubyMergeAdapter],\n ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n return adapters.get(language);\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc. This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n // Check if the existing docstring contains @deprecated anywhere\n if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n // If generated doc already has @deprecated, no need to merge\n if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n // Extract the @deprecated content from the existing doc.\n // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n const deprecatedParts: string[] = [];\n for (const line of existingDoc.split('\\n')) {\n if (/@deprecated\\b/.test(line)) {\n // Normalize to JSDoc member format: ` * @deprecated ...`\n const match = line.match(/@deprecated\\b.*/);\n if (match) {\n // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n deprecatedParts.push(` * ${cleaned}`);\n }\n }\n }\n if (deprecatedParts.length === 0) return generatedDoc;\n\n // Insert @deprecated lines before the closing */ of the generated doc\n const closingIdx = generatedDoc.lastIndexOf('*/');\n if (closingIdx === -1) return generatedDoc;\n const before = generatedDoc.slice(0, closingIdx);\n const after = generatedDoc.slice(closingIdx);\n return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n startIndex: number;\n endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n const regions: IgnoredRegion[] = [];\n const startTag = '@oagen-ignore-start';\n const endTag = '@oagen-ignore-end';\n let searchFrom = 0;\n\n while (true) {\n const startIdx = source.indexOf(startTag, searchFrom);\n if (startIdx === -1) break;\n const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n if (endIdx === -1) break; // Unclosed — silently ignore\n regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n searchFrom = endIdx + endTag.length;\n }\n\n return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n if (regions.length === 0) return new Set();\n const ignored = new Set<string>();\n for (const [name, info] of docstrings) {\n if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n ignored.add(name);\n }\n }\n return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n if (!Number.isFinite(value)) return 0;\n if (value < 0) return 0;\n if (value > contentLength) return contentLength;\n return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n const idx = clampIndex(declStartIndex, content.length);\n const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n content: string,\n docText: string,\n declStartIndex: number,\n fallbackStart: number,\n fallbackEnd: number,\n): { start: number; end: number } {\n const safeDecl = clampIndex(declStartIndex, content.length);\n const safeFallbackStart = clampIndex(fallbackStart, content.length);\n const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n const found = content.lastIndexOf(docText, safeDecl);\n if (found !== -1) {\n return { start: found, end: found + docText.length };\n }\n return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n const cached = parserCache.get(language);\n if (cached) return cached;\n\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(\n `No tree-sitter grammar configured for language \"${language}\". ` +\n `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n );\n }\n\n const mod = await import(adapter.grammarModule);\n const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n const grammar = (exported as { default?: unknown }).default ?? exported;\n const parser = new Parser();\n parser.setLanguage(grammar);\n parserCache.set(language, parser);\n return parser;\n}\n\ninterface ParsedSymbols {\n names: Set<string>;\n /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n if (typeof source !== 'string') {\n throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n }\n const tree = safeParse(parser, source);\n const names = new Set<string>();\n const unnamedTexts = new Set<string>();\n const parsed = adapter.parseStatements(tree, source);\n\n for (const imp of parsed.imports) {\n names.add(imp.key);\n }\n for (const statement of parsed.statements) {\n if (statement.key) {\n names.add(statement.key);\n } else {\n unnamedTexts.add(statement.text.trim());\n }\n }\n\n return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n const tree = safeParse(parser, source);\n return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter. `bodyEndLine` is 0-based. For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n source: string,\n language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n const parser = await getParser(language);\n const tree = safeParse(parser, source);\n const map = new Map<string, { bodyEndLine: number }>();\n\n function processClassNode(node: Parser.SyntaxNode): void {\n const nameNode =\n node.childForFieldName('name') ??\n node.children.find((c) => c.type === 'type_identifier' || c.type === 'identifier');\n if (!nameNode) return;\n const name = nameNode.text;\n\n const body =\n node.childForFieldName('body') ?? node.children.find((c) => c.type === 'class_body' || c.type === 'body');\n const endRow = body ? body.endPosition.row : node.endPosition.row;\n const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n if (lastChar === '}') {\n map.set(name, { bodyEndLine: endRow });\n } else {\n map.set(name, { bodyEndLine: endRow + 1 });\n }\n }\n\n // Walk the tree recursively. Ruby (and Python) often nest target classes\n // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n // root children would miss them.\n function walk(node: Parser.SyntaxNode): void {\n if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n processClassNode(node);\n }\n if (node.type === 'decorated_definition') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_definition') processClassNode(inner);\n }\n }\n if (node.type === 'export_statement') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_declaration') processClassNode(inner);\n }\n }\n for (const child of node.namedChildren) walk(child);\n }\n for (const child of tree.rootNode.children) {\n walk(child);\n }\n\n return map;\n}\n\nexport interface MergeResult {\n content: string;\n added: number;\n preserved: number;\n changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n existingContent: string,\n generatedContent: string,\n language: string,\n header: string,\n): Promise<MergeResult> {\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n\n // Parse existing file once — extract both symbols and statements from the same AST pass\n const existingStatements = await extractStatements(existingContent, language);\n const generatedStatements = await extractStatements(generatedContent, language);\n\n const existingKeys = new Set<string>();\n const existingUnnamedTexts = new Set<string>();\n const existingImportKeys = new Set<string>();\n const existingReexports = new Set<string>();\n let lastImportEndIndex = -1;\n\n // Collect import keys AND imported identifiers (to prevent adding declarations\n // that clash with already-imported names)\n const existingImportedNames = new Set<string>();\n for (const imp of existingStatements.imports) {\n existingImportKeys.add(imp.key);\n // Extract identifiers from import text: import { Foo, Bar } from '...'\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const name of braceMatch[1].split(',')) {\n const trimmed = name.replace(/\\btype\\b/, '').trim();\n if (trimmed) existingImportedNames.add(trimmed);\n }\n }\n }\n for (const anchor of existingStatements.importAnchors) {\n const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n const stmtLines = anchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n const linesBefore =\n existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n 1;\n const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n\n // Track all names exported by existing statements (both direct exports and\n // re-export aliases like `export { X as Y }`). Used to prevent the merger\n // from appending a re-export that introduces a duplicate exported name.\n const existingExportedNames = new Set<string>();\n\n for (const stmt of existingStatements.statements) {\n if (stmt.kind === 'reexport') {\n existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n // Collect aliased export names from re-exports\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const part of braceMatch[1].split(',')) {\n const segments = part.trim().split(/\\s+as\\s+/);\n const exportedName = (segments[1] ?? segments[0]).trim();\n if (exportedName) existingExportedNames.add(exportedName);\n }\n }\n }\n if (stmt.key) {\n existingKeys.add(stmt.key);\n existingExportedNames.add(stmt.key);\n } else {\n existingUnnamedTexts.add(stmt.text.trim());\n }\n }\n\n const headerLine = header.trim();\n\n const newImports: MergeImport[] = [];\n const toAppend: string[] = [];\n let preserved = 0;\n\n for (const imp of generatedStatements.imports) {\n if (imp.text.trim() === headerLine) continue;\n if (existingImportKeys.has(imp.key)) {\n // The existing file already imports from this module path.\n // Check if the generated import adds identifiers not present in\n // the existing import — if so, create a supplemental import with\n // only the new identifiers. The supplemental participates in the\n // usage-based filter (below) so unused identifiers are dropped.\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n if (newNames.length > 0) {\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n newImports.push({\n key: imp.key + '#supplemental',\n text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n }\n }\n }\n preserved++;\n continue;\n }\n // Strip out identifiers that are already imported from another path.\n // This prevents duplicates when the generated file uses a specific path\n // (e.g., '../interfaces/organization.interface') while the existing file\n // imports the same names from a barrel (e.g., '../interfaces').\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n // Check against both existing imports AND existing top-level declarations\n const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n if (names.length > 0 && names.every(isAlreadyDefined)) {\n preserved++;\n continue;\n }\n // If only SOME identifiers are already defined, strip them out and keep only new ones\n if (names.some(isAlreadyDefined)) {\n const newNames = names.filter((n) => !isAlreadyDefined(n));\n if (newNames.length === 0) {\n preserved++;\n continue;\n }\n // Rebuild the import with only new identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n newImports.push({ key: imp.key, text: newText });\n continue;\n }\n }\n }\n newImports.push(imp);\n }\n\n for (const stmt of generatedStatements.statements) {\n // Skip the header comment\n if (stmt.text.trim() === headerLine) continue;\n\n // Skip re-export statements that duplicate existing re-exports\n // (e.g., generated uses .js extension but existing doesn't).\n // Allow genuinely new re-exports through.\n if (stmt.kind === 'reexport') {\n const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n preserved++;\n continue;\n }\n // Also skip re-exports whose aliased names are already defined as\n // top-level exports in the existing file (e.g., generated file has\n // `export { X as deserializeFoo } from '...'` but existing file\n // already has `export const deserializeFoo = ...`).\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const exportedNames = braceMatch[1]\n .split(',')\n .map((n) => {\n const parts = n.trim().split(/\\s+as\\s+/);\n return (parts[1] ?? parts[0]).trim();\n })\n .filter(Boolean);\n if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n preserved++;\n continue;\n }\n }\n }\n\n if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n preserved++;\n continue;\n }\n\n if (!stmt.key) {\n if (existingUnnamedTexts.has(stmt.text.trim())) {\n preserved++;\n continue;\n }\n }\n\n toAppend.push(stmt.text);\n }\n\n if (newImports.length === 0 && toAppend.length === 0) {\n // No top-level changes — check for deep merge before returning\n if (!adapter.extractMembers) {\n // Still need to check docstring refresh below\n }\n }\n\n let result = existingContent;\n\n // Append new top-level symbols first (so deep merge can see them)\n if (toAppend.length > 0) {\n result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n }\n\n // Deep merge pass: add new members to existing symbols\n // Runs after import/symbol merge so line numbers are based on the updated content\n let deepAdded = 0;\n let deepPruned = 0;\n const insertions: { line: number; text: string }[] = [];\n if (adapter.extractMembers) {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultSymbols = adapter.extractMembers(resultTree, result);\n const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n const existingTree = safeParse(parser, existingContent);\n const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n const deepIgnoredRegions = findIgnoredRegions(existingContent);\n const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n // Pass 1: prune stale \"managed\" members (existing members the adapter\n // recognizes as generator-owned but that no longer appear in the\n // regenerated content — e.g. accessors whose mount target was remapped).\n // Done as byte-range deletes before line-based insertions so insertion\n // line numbers stay valid for the post-prune result.\n if (adapter.isManagedMember) {\n const pruneEdits: { start: number; end: number }[] = [];\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue;\n const genMemberKeys = new Set(genSymbol.members.map((m) => m.key));\n for (const existMember of existSymbol.members) {\n if (genMemberKeys.has(existMember.key)) continue;\n if (existMember.startIndex === undefined || existMember.endIndex === undefined) continue;\n if (!adapter.isManagedMember(existMember)) continue;\n pruneEdits.push({ start: existMember.startIndex, end: existMember.endIndex });\n }\n }\n if (pruneEdits.length > 0) {\n pruneEdits.sort((a, b) => b.start - a.start);\n for (const edit of pruneEdits) {\n let end = edit.end;\n while (end < result.length && (result[end] === ' ' || result[end] === '\\t')) end++;\n if (result[end] === '\\n') end++;\n result = result.slice(0, edit.start) + result.slice(end);\n }\n deepPruned = pruneEdits.length;\n // Re-extract since byte offsets and line numbers shifted.\n const reTree = safeParse(parser, result);\n resultSymbols.clear();\n for (const [k, v] of adapter.extractMembers(reTree, result)) resultSymbols.set(k, v);\n }\n }\n\n // Pass 2: append new members the regenerated content adds.\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue; // New symbol — handled by top-level append\n\n const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n if (newMembers.length > 0) {\n // Let the adapter decide whether to skip deep merge (e.g., when new members\n // reference dependencies the existing symbol doesn't provide)\n if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n continue;\n }\n\n const indent = existSymbol.memberIndent ?? ' ';\n const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n // Leading blank line separates inserted members from existing ones.\n insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n deepAdded += newMembers.length;\n }\n }\n\n if (insertions.length > 0) {\n // Apply bottom-up to avoid offset shifting\n insertions.sort((a, b) => b.line - a.line);\n const resultLines = result.split('\\n');\n for (const ins of insertions) {\n resultLines.splice(ins.line, 0, ins.text);\n }\n result = resultLines.join('\\n');\n }\n }\n\n // Insert new imports only when new symbols or members were actually added.\n // This prevents orphaned imports for generated code that wasn't merged in.\n // Additionally, filter imports to only include identifiers actually used in the\n // appended/inserted code — prevents orphaned imports for generated code that\n // referenced types used in other (non-appended) generated functions.\n if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n // Build text of all new code that was actually added (appended + deep-merged members)\n const addedParts: string[] = [...toAppend];\n if (insertions) {\n for (const ins of insertions) {\n addedParts.push(ins.text);\n }\n }\n const addedCodeText = addedParts.join('\\n');\n\n // Filter imports to only identifiers that appear in the added code.\n // Strip individual unused identifiers from each import rather than\n // keeping/dropping the entire import — prevents orphaned imports when\n // a generated import line contains both used and unused identifiers\n // (e.g., `import { deserializeFoo, serializeFoo }` where only\n // serializeFoo is used in the appended code).\n const filteredImports: MergeImport[] = [];\n for (const imp of newImports) {\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (!braceMatch) {\n // Non-destructured import (e.g., default import) — keep as-is\n filteredImports.push(imp);\n continue;\n }\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const usedNames = names.filter((name) => addedCodeText.includes(name));\n if (usedNames.length === 0) continue; // Drop entirely\n if (usedNames.length === names.length) {\n // All identifiers used — keep original import\n filteredImports.push(imp);\n } else {\n // Rebuild import with only used identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n filteredImports.push({\n key: imp.key,\n text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n } else {\n filteredImports.push(imp);\n }\n }\n }\n\n if (filteredImports.length > 0) {\n const renderedImports = adapter.renderImports\n ? adapter.renderImports(filteredImports)\n : filteredImports.map((entry) => entry.text);\n const lines = result.split('\\n');\n const insertIdx = lastImportEndIndex + 1;\n lines.splice(insertIdx, 0, ...renderedImports);\n result = lines.join('\\n');\n }\n }\n\n // Docstring refresh pass: update existing docstrings to match generated content\n let docstringUpdates = 0;\n {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultDocs = adapter.extractDocstrings(resultTree, result);\n const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n const docIgnoredRegions = findIgnoredRegions(result);\n const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n const edits: { start: number; end: number; newText: string }[] = [];\n\n for (const [symbolName, genInfo] of generatedDocs) {\n const existInfo = resultDocs.get(symbolName);\n if (!existInfo) continue;\n if (docIgnoredSymbols.has(symbolName)) continue;\n\n // Skip header comments being treated as docstrings\n const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n // Top-level docstring\n if (genDoc) {\n if (existInfo.docstring) {\n const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n const range = resolveDocRange(\n result,\n existInfo.docstring.text,\n existInfo.declStartIndex,\n existInfo.docstring.startIndex,\n existInfo.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n const indent = ' '.repeat(existInfo.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genDoc.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — first pass: match by name\n const matchedExistMembers = new Set<string>();\n for (const [memberName, genMember] of genInfo.members) {\n const existMember = existInfo.members.get(memberName);\n if (!existMember) continue;\n matchedExistMembers.add(memberName);\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — second pass: URL fingerprint fallback\n // Match generated members to existing members by URL pattern when\n // name-based matching fails (e.g., generated \"find\" vs existing \"getWidget\"\n // both call this.client.get('/widgets/${id}')).\n //\n // Safety: only attempt fingerprint matching when there is exactly ONE\n // unmatched generated member and ONE unmatched existing member for a\n // given fingerprint. When multiple members share the same URL path\n // (e.g., POST and GET on /authorization/roles), fingerprint matching\n // is ambiguous and would swap docstrings between methods.\n const unmatchedGenByFp = new Map<\n string,\n { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [genName, genMember] of genInfo.members) {\n if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n if (!genMember.docstring || !genMember.urlFingerprint) continue;\n // Skip if this generated member was already name-matched\n if (existInfo.members.has(genName)) continue;\n const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n bucket.push({ name: genName, member: genMember });\n unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n }\n const unmatchedExistByFp = new Map<\n string,\n { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [existName, existMember] of existInfo.members) {\n if (matchedExistMembers.has(existName)) continue;\n if (!existMember.urlFingerprint) continue;\n const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n bucket.push({ name: existName, member: existMember });\n unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n }\n for (const [fp, genBucket] of unmatchedGenByFp) {\n if (genBucket.length !== 1) continue; // ambiguous — skip\n const existBucket = unmatchedExistByFp.get(fp);\n if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n const genMember = genBucket[0].member;\n const existEntry = existBucket[0];\n const existMember = existEntry.member;\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (isPreserved) continue;\n if (existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n matchedExistMembers.add(existEntry.name);\n }\n }\n\n if (edits.length > 0) {\n edits.sort((a, b) => b.start - a.start);\n for (const edit of edits) {\n result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n }\n }\n }\n\n const importsActuallyAdded =\n toAppend.length > 0 || deepAdded > 0\n ? adapter.renderImports\n ? adapter.renderImports(newImports).length\n : newImports.length\n : 0;\n const topLevelAdded = importsActuallyAdded + toAppend.length;\n const totalAdded = topLevelAdded + deepAdded;\n\n if (totalAdded === 0 && docstringUpdates === 0 && deepPruned === 0) {\n return { content: existingContent, added: 0, preserved, changed: false };\n }\n\n return {\n content: result,\n added: totalAdded,\n preserved,\n changed: true,\n };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n if (\n typeof existing === 'object' &&\n existing !== null &&\n !Array.isArray(existing) &&\n typeof generated === 'object' &&\n generated !== null &&\n !Array.isArray(generated)\n ) {\n const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n if (key in merged) {\n merged[key] = deepMergeJson(merged[key], value);\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n // Arrays and primitives: generated wins\n return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines, extractStatements } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n * tree-sitter grammar for AST-level merging. */\n language?: string;\n /** The auto-generated file header string. */\n header?: string;\n}\n\nexport interface WriteResult {\n written: string[];\n merged: string[];\n skipped: string[];\n identical: string[];\n ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n files: GeneratedFile[],\n outputDir: string,\n options?: WriteOptions,\n): Promise<WriteResult> {\n const result: WriteResult = {\n written: [],\n merged: [],\n skipped: [],\n identical: [],\n ignored: [],\n };\n const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n const language = options?.language;\n const header = options?.header ?? '';\n\n for (const file of sorted) {\n const fullPath = path.join(outputDir, file.path);\n\n // Repair on-disk casing when an emitter renames a generated file in a\n // case-only way (e.g. `AuthenticationMfaFailed.kt` → `AuthenticationMFAFailed.kt`\n // after adding `MFA` to an acronym list). On case-insensitive filesystems\n // (APFS, NTFS) `writeFile` would otherwise reuse the existing inode and\n // preserve the stale casing — surfacing later as ktlint/eslint errors.\n await renameMismatchedCasing(fullPath);\n\n // Check if file already exists\n let existingContent: string | null = null;\n try {\n existingContent = await fs.readFile(fullPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n // New file → write in full\n if (existingContent === null) {\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // skipIfExists → hard skip, no merge (but ensure header is present).\n // JSON files are skipped from header injection because a leading `//`\n // comment makes the file invalid JSON.\n if (file.skipIfExists) {\n if (header && !existingContent.startsWith(header) && !file.path.endsWith('.json')) {\n await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n }\n result.skipped.push(file.path);\n continue;\n }\n\n // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n if (existingContent.includes('@oagen-ignore-file')) {\n result.ignored.push(file.path);\n continue;\n }\n\n // Don't merge test files into hand-written test files — generated tests are\n // designed for the standalone generated SDK and will have wrong\n // signatures/fixtures when merged into hand-written tests.\n // However, if the existing test file is itself auto-generated (has the oagen\n // header), allow overwriteExisting to take effect so new methods get coverage.\n const adapter = language ? getMergeAdapter(language) : undefined;\n const isTestFile = adapter?.testFilePatterns\n ? adapter.testFilePatterns.some((p) => p.test(file.path))\n : isDefaultTestFile(file.path);\n if (isTestFile) {\n const isExistingAutoGenerated = header && existingContent.startsWith(header);\n if (!isExistingAutoGenerated && !file.overwriteExisting) {\n result.skipped.push(file.path);\n continue;\n }\n // Auto-generated test file or overwriteExisting — fall through to overwriteExisting / identical checks\n }\n\n // Identical content → no-op\n if (existingContent === file.content) {\n result.identical.push(file.path);\n continue;\n }\n\n // Force overwrite — but preserve any @oagen-ignore regions from existing content\n if (file.overwriteExisting) {\n const content =\n existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n : file.content;\n await fs.writeFile(fullPath, content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // JSON files → deep merge preserving existing keys\n if (file.path.endsWith('.json')) {\n try {\n const existingJson = JSON.parse(existingContent);\n const generatedJson = JSON.parse(file.content);\n const merged = deepMergeJson(existingJson, generatedJson);\n const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n if (mergedContent === existingContent) {\n result.identical.push(file.path);\n } else {\n await fs.writeFile(fullPath, mergedContent, 'utf-8');\n result.merged.push(file.path);\n }\n } catch {\n // Parse failed — fall back to overwrite\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n }\n continue;\n }\n\n // Source files with grammar → AST-level merge\n if (language && hasGrammar(language)) {\n try {\n const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n // Ensure header is present on merged content\n let finalContent = mergeResult.content;\n if (header && !finalContent.startsWith(header)) {\n finalContent = header + '\\n\\n' + finalContent;\n }\n\n if (!mergeResult.changed && finalContent === existingContent) {\n result.identical.push(file.path);\n continue;\n }\n\n await fs.writeFile(fullPath, finalContent, 'utf-8');\n result.merged.push(file.path);\n continue;\n } catch (err) {\n // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n console.warn(\n `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n );\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n }\n\n // No grammar available → skip to avoid clobbering\n result.skipped.push(file.path);\n }\n\n return result;\n}\n\n/**\n * If a sibling exists with the same name except for letter case, rename it to\n * the requested casing. Uses a two-step rename via a temporary unique name so\n * case-insensitive filesystems (APFS on macOS, NTFS on Windows) actually\n * update the entry — `rename('Foo', 'FOO')` is a no-op on those systems.\n */\nasync function renameMismatchedCasing(fullPath: string): Promise<void> {\n const dir = path.dirname(fullPath);\n const target = path.basename(fullPath);\n let entries: string[];\n try {\n entries = await fs.readdir(dir);\n } catch {\n return;\n }\n if (entries.includes(target)) return;\n const targetLower = target.toLowerCase();\n const mismatch = entries.find((e) => e.toLowerCase() === targetLower);\n if (!mismatch) return;\n const oldPath = path.join(dir, mismatch);\n const tempPath = path.join(dir, `.oagen-case-${process.pid}-${Date.now()}-${target}`);\n await fs.rename(oldPath, tempPath);\n await fs.rename(tempPath, fullPath);\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n return (\n /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n filePath.endsWith('_test.go') ||\n filePath.endsWith('_test.rb') ||\n filePath.endsWith('_spec.rb') ||\n /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n filePath.endsWith('_test.py') ||\n filePath.endsWith('Test.php') ||\n filePath.endsWith('_test.rs') ||\n /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n existingContent: string,\n generatedContent: string,\n language: string,\n): Promise<string> {\n const existingLines = existingContent.split('\\n');\n const generatedLines = generatedContent.split('\\n');\n\n // 1. Extract ignore blocks, their containing class, and the anchor line\n // (first non-blank line after the block in the existing file).\n const blocks: { containingClass: string; containingScope: string; lines: string[]; anchor: string }[] = [];\n for (let i = 0; i < existingLines.length; i++) {\n if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n const startIdx = i;\n while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n let anchor = '';\n for (let a = i + 1; a < existingLines.length; a++) {\n if (existingLines[a].trim()) {\n anchor = existingLines[a].trimStart();\n break;\n }\n }\n blocks.push({\n containingClass: findContainingClass(existingLines, startIdx),\n containingScope: findContainingDescribeScope(existingLines, startIdx),\n lines: existingLines.slice(startIdx, i + 1),\n anchor,\n });\n }\n if (blocks.length === 0) return generatedContent;\n\n // 2. Splice extra imports from existing into generated.\n // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n // generator itself emitted: we are about to re-insert the on-disk versions,\n // and if we left the generator's seed blocks in place we'd end up with two\n // copies of every ignore block per regeneration (monotonically growing).\n const result = stripIgnoreRegions(generatedLines);\n spliceExtraImports(existingLines, result);\n\n // 3. Build class-end map from the generated content (after import splicing)\n // via tree-sitter for accurate boundary detection.\n const genSource = result.join('\\n');\n const classEndLines = await extractClassEndLines(genSource, language);\n\n // 4. Group ignore blocks by class and determine insertion points\n const blocksByClass = new Map<string, Array<{ containingScope: string; lines: string[]; anchor: string }>>();\n for (const b of blocks) {\n if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n blocksByClass.get(b.containingClass)!.push({\n containingScope: b.containingScope,\n lines: b.lines,\n anchor: b.anchor,\n });\n }\n\n // 4a. Handle replacement blocks: ignore blocks that redefine their\n // containing class replace the generated class entirely.\n // Also handles top-level blocks (no containing class) that define\n // a class matching one in the generated content.\n const replacedClasses = new Set<string>();\n const handledBlockKeys = new Set<string>();\n const replacements: {\n startLine: number;\n endLine: number;\n content: string[];\n }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n // Determine the target class for replacement. When the block has a\n // containing class, we check if the block redefines that class. When\n // there is no containing class (top-level ignore block), we look for a\n // class definition inside the block that matches a generated class.\n let targetClass = className;\n if (!targetClass) {\n for (const entry of classBlocks) {\n for (const l of entry.lines) {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n if (m && classEndLines.has(m[1])) {\n targetClass = m[1];\n break;\n }\n }\n if (targetClass) break;\n }\n }\n if (!targetClass) continue;\n const isReplacement = classBlocks.some((entry) =>\n entry.lines.some((l) => {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n return m?.[1] === targetClass;\n }),\n );\n if (!isReplacement) continue;\n const info = classEndLines.get(targetClass);\n if (!info) continue;\n const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n if (startLine < 0) continue;\n const content: string[] = [];\n for (const entry of classBlocks) {\n content.push('');\n content.push(...entry.lines);\n }\n replacements.push({ startLine, endLine: info.bodyEndLine, content });\n replacedClasses.add(targetClass);\n handledBlockKeys.add(className);\n }\n // Apply replacements bottom-up to preserve line indices\n replacements.sort((a, b) => b.startLine - a.startLine);\n for (const rep of replacements) {\n result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n }\n\n // 4a-bis. Top-level declarations protected by ignore regions win over their\n // generated counterparts. For each top-level block, drop generated\n // declarations (interface/type/const/function/…) whose names are\n // declared inside the block; the block content replaces the first\n // such declaration in place. Without this, every regeneration\n // re-emits a duplicate of each region-protected declaration.\n let regionDeclarationEdits = 0;\n {\n const topLevelEntries = blocksByClass.get('');\n if (topLevelEntries) {\n // When 4a already placed the top-level blocks (as part of a class\n // replacement), only delete generated duplicates — never re-insert.\n const alreadyPlaced = handledBlockKeys.has('');\n const remaining: typeof topLevelEntries = [];\n for (const entry of topLevelEntries) {\n const outcome = await applyRegionDeclarationOverride(result, entry.lines, language, !alreadyPlaced);\n if (outcome.edited) regionDeclarationEdits++;\n if (!alreadyPlaced && !outcome.placed) remaining.push(entry);\n }\n if (!alreadyPlaced) {\n if (remaining.length === 0) {\n blocksByClass.delete('');\n } else {\n blocksByClass.set('', remaining);\n }\n }\n }\n }\n\n // 4b. Standard insertions for non-replacement blocks\n // Rebuild class end lines if replacements shifted line numbers.\n let effectiveClassEndLines = classEndLines;\n if (replacedClasses.size > 0 || regionDeclarationEdits > 0) {\n effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n }\n\n const insertions: { line: number; order: number; content: string[] }[] = [];\n let insertionOrder = 0;\n for (const [className, classBlocks] of blocksByClass) {\n if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n const info = className ? effectiveClassEndLines.get(className) : undefined;\n\n // Insert each block individually so each can use its own anchor.\n for (const entry of classBlocks) {\n let insertLine: number | undefined;\n\n // Try anchor-based positioning: find the first line in the generated\n // file whose trimmed-start content matches the anchor (the first\n // non-blank line that followed this block in the existing file).\n // Skip anchors that are just punctuation (braces, etc.) since they\n // match too many locations. Accept doc comment starters (/** /// #)\n // as valid anchors since they're structurally meaningful.\n // Also skip bare language keywords (`end`, `end;`, `end)`) that appear\n // on many lines and would match the wrong location (e.g. nesting the\n // block inside a Ruby method body instead of at class level).\n const isAmbiguousAnchor = /^end[;)\\s]*$/.test(entry.anchor);\n if (\n entry.anchor &&\n !entry.anchor.includes('@oagen-ignore') &&\n !isAmbiguousAnchor &&\n /[a-zA-Z]|^\\/\\*|^\\/\\//.test(entry.anchor)\n ) {\n for (let li = 0; li < result.length; li++) {\n if (result[li].trimStart() === entry.anchor) {\n insertLine = li;\n break;\n }\n }\n }\n\n // Fallback: class body end, or for top-level import blocks, after the\n // last import line (so they stay near the top of the file, not at the\n // bottom where they'd trigger E402 lint errors).\n if (insertLine === undefined) {\n if (info) {\n insertLine = info.bodyEndLine;\n } else {\n const scopeEndLine = entry.containingScope\n ? findDescribeScopeEndLine(result, entry.containingScope)\n : undefined;\n const blockHasImportsFallback = entry.lines.some((l: string) => /^\\s*(import|from)\\s/.test(l));\n if (scopeEndLine !== undefined) {\n insertLine = scopeEndLine;\n } else if (blockHasImportsFallback || hasTopLevelDeclaration(entry.lines)) {\n let lastImportLine = 0;\n for (let li = 0; li < result.length; li++) {\n const trimmed = result[li].trimStart();\n if (/^(import|from)\\s/.test(trimmed)) lastImportLine = li + 1;\n }\n insertLine = lastImportLine;\n } else {\n insertLine = result.length;\n }\n }\n }\n\n // When inserting an import-containing ignore block, move up past\n // blank separator lines so the block sits flush with surrounding\n // imports (e.g., Kotlin's ktlint forbids blank lines within import\n // blocks).\n const blockHasImports = entry.lines.some((l: string) => /^\\s*import\\s/.test(l));\n if (blockHasImports) {\n while (\n insertLine >= 2 &&\n result[insertLine - 1]?.trim() === '' &&\n /^\\s*(import|using|from)\\s/.test(result[insertLine - 2] ?? '')\n ) {\n insertLine--;\n }\n }\n\n // Skip the leading blank line when the block is adjacent to imports\n // or already preceded by a blank line (avoids double-blank-line gaps).\n // Exclude C# `using` directives — StyleCop SA1515 requires a blank\n // line before comments, so collapsing breaks the build.\n const prevLine = insertLine > 0 ? (result[insertLine - 1]?.trimStart() ?? '') : '';\n const prevIsImport = /^import\\s/.test(prevLine) || /^from\\s/.test(prevLine);\n const prevIsBlank = insertLine > 0 && prevLine === '';\n const blockContent = prevIsImport || prevIsBlank ? [...entry.lines] : ['', ...entry.lines];\n // Add a trailing blank line when the next line is a doc comment\n // (C# SA1514 requires a blank line before `///` doc headers).\n const nextLine = result[insertLine]?.trimStart() ?? '';\n if (nextLine.startsWith('///')) {\n blockContent.push('');\n }\n insertions.push({ line: insertLine, order: insertionOrder++, content: blockContent });\n }\n }\n\n // Apply bottom-up to preserve line indices. Blocks with the same insertion\n // line must be applied in reverse discovery order because each splice inserts\n // at the same index; otherwise repeated generation flips their order.\n insertions.sort((a, b) => b.line - a.line || b.order - a.order);\n for (const ins of insertions) {\n result.splice(ins.line, 0, ...ins.content);\n }\n\n removeDuplicateImportsCoveredByIgnoreBlocks(result);\n\n return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n // Drop a preceding blank line if we have one queued up — otherwise\n // regen leaves a stray blank line above the spliced-in block.\n while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n if (/^\\S/.test(lines[lineIdx] ?? '')) return '';\n // Allow leading whitespace and language-specific modifiers before `class`.\n // Covers: `public class Foo` (C#/Java), `export class Foo` (TS),\n // `class Foo` (Python/Ruby), `internal sealed class Foo` (C#), etc.\n for (let j = lineIdx - 1; j >= 0; j--) {\n const m = lines[j].match(\n /^\\s*(?:(?:export|public|private|protected|internal|abstract|sealed|static|partial)\\s+)*class\\s+(\\w+)/,\n );\n if (m) return m[1];\n }\n return '';\n}\n\nfunction findContainingDescribeScope(lines: string[], lineIdx: number): string {\n const markerLine = lines[lineIdx] ?? '';\n if (/^\\S/.test(markerLine)) return '';\n const markerIndent = leadingSpaces(markerLine);\n for (let j = lineIdx - 1; j >= 0; j--) {\n const line = lines[j];\n const indent = leadingSpaces(line);\n if (indent >= markerIndent) continue;\n const match = line.match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n if (match) return match[2];\n if (/^\\s*(?:export\\s+)?class\\s+\\w+/.test(line)) return '';\n }\n return '';\n}\n\nfunction findDescribeScopeEndLine(lines: string[], scopeName: string): number | undefined {\n for (let i = 0; i < lines.length; i++) {\n const match = lines[i].match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n if (!match || match[2] !== scopeName) continue;\n\n let depth = 0;\n for (let j = i; j < lines.length; j++) {\n depth += countChar(lines[j], '{');\n depth -= countChar(lines[j], '}');\n if (j > i && depth <= 0) return j;\n }\n }\n return undefined;\n}\n\nfunction leadingSpaces(line: string): number {\n return line.match(/^\\s*/)?.[0].length ?? 0;\n}\n\nfunction countChar(line: string, char: string): number {\n return [...line].filter((c) => c === char).length;\n}\n\nfunction hasTopLevelDeclaration(lines: string[]): boolean {\n return lines.some((line) =>\n /^(?:export\\s+)?(?:interface|type|class|function|const|let|var|enum)\\s+\\w+/.test(line.trim()),\n );\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n // Match optional indentation so Ruby/Python nested classes are found.\n const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n for (let i = beforeLine - 1; i >= 0; i--) {\n if (!classPattern.test(lines[i])) continue;\n // Scan backward past decorators\n let start = i;\n while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n start--;\n }\n return start;\n }\n return -1;\n}\n\n// --- region-protected top-level declaration overrides ---\n\n/**\n * Conservative top-level declaration matcher for ignore-block content.\n * Matches column-0 declarations like `export interface X`, `type X = …`,\n * `const X = …`, `function X(…)`, `class X` (export optional). Names found\n * here are only acted on when the language's merge adapter also reports a\n * generated top-level statement with the same key, so false positives are\n * filtered by the real parser.\n */\nconst REGION_DECLARATION_PATTERN =\n /^(?:export\\s+)?(?:declare\\s+)?(?:interface|type|enum|class|const|let|var|async\\s+function|function)\\s+([A-Za-z_$][\\w$]*)/;\n\n/** Extract top-level symbol names declared inside an ignore block's lines. */\nfunction collectRegionDeclaredNames(blockLines: string[]): Set<string> {\n const names = new Set<string>();\n for (const line of blockLines) {\n if (line.includes('@oagen-ignore')) continue;\n const m = line.match(REGION_DECLARATION_PATTERN);\n if (m) names.add(m[1]);\n }\n return names;\n}\n\n/** Inclusive line ranges of `@oagen-ignore-start`..`@oagen-ignore-end` regions. */\nfunction collectIgnoreRegionLineRanges(lines: string[]): Array<{ start: number; end: number }> {\n const ranges: Array<{ start: number; end: number }> = [];\n let start = -1;\n for (let i = 0; i < lines.length; i++) {\n if (start === -1 && lines[i].includes('@oagen-ignore-start')) {\n start = i;\n continue;\n }\n if (start !== -1 && lines[i].includes('@oagen-ignore-end')) {\n ranges.push({ start, end: i });\n start = -1;\n }\n }\n return ranges;\n}\n\n/**\n * Walk upward from a declaration's first line over its contiguous comment\n * block (doc comment), so the comment is dropped together with the\n * declaration. Stops at blank lines, region markers, and line 0 (a comment\n * on line 0 is the file header, not a docstring).\n */\nfunction extendOverPrecedingComments(lines: string[], startLine: number): number {\n let s = startLine;\n while (s > 1) {\n const prev = lines[s - 1].trim();\n if (prev === '' || prev.includes('@oagen-ignore')) break;\n const isComment = prev.startsWith('//') || prev.startsWith('/*') || prev.startsWith('*') || prev.startsWith('#');\n if (!isComment) break;\n s--;\n }\n return s;\n}\n\n/**\n * Drop generated top-level declarations that are redeclared inside an ignore\n * block (\"region wins\"). When `placeBlock` is set and at least one generated\n * declaration matches, the block's lines replace the first match in place\n * (mirroring the class-replacement behavior above); any further matches are\n * deleted. Mutates `result` in place.\n *\n * Returns `placed` (the block content now lives in `result` and must not be\n * inserted again) and `edited` (line numbers shifted).\n */\nasync function applyRegionDeclarationOverride(\n result: string[],\n blockLines: string[],\n language: string,\n placeBlock: boolean,\n): Promise<{ placed: boolean; edited: boolean }> {\n const names = collectRegionDeclaredNames(blockLines);\n if (names.size === 0) return { placed: false, edited: false };\n\n const source = result.join('\\n');\n let parsed;\n try {\n parsed = await extractStatements(source, language);\n } catch {\n return { placed: false, edited: false };\n }\n\n const regionRanges = collectIgnoreRegionLineRanges(result);\n const inRegion = (line: number) => regionRanges.some((r) => line >= r.start && line <= r.end);\n\n const spans: Array<{ start: number; end: number }> = [];\n for (const stmt of parsed.statements) {\n if (stmt.kind !== 'declaration' || !stmt.key || !names.has(stmt.key)) continue;\n // Locate the statement's line span; skip occurrences inside ignore\n // regions (those ARE the protected content).\n let idx = source.indexOf(stmt.text);\n let startLine = -1;\n while (idx !== -1) {\n const line = source.slice(0, idx).split('\\n').length - 1;\n if (!inRegion(line)) {\n startLine = line;\n break;\n }\n idx = source.indexOf(stmt.text, idx + 1);\n }\n if (startLine === -1) continue;\n const endLine = startLine + stmt.text.split('\\n').length - 1;\n spans.push({ start: extendOverPrecedingComments(result, startLine), end: endLine });\n }\n if (spans.length === 0) return { placed: false, edited: false };\n\n spans.sort((a, b) => a.start - b.start);\n\n // Delete all matches after the first, bottom-up to preserve indices.\n for (let i = spans.length - 1; i >= 1; i--) {\n const span = spans[i];\n let deleteCount = span.end - span.start + 1;\n // Collapse the blank separator the deletion leaves behind.\n const prevBlank = span.start === 0 || (result[span.start - 1] ?? '').trim() === '';\n const nextBlank = (result[span.end + 1] ?? '').trim() === '';\n if (prevBlank && nextBlank && span.end + 1 < result.length) deleteCount++;\n result.splice(span.start, deleteCount);\n }\n\n const first = spans[0];\n if (placeBlock) {\n result.splice(first.start, first.end - first.start + 1, ...blockLines);\n return { placed: true, edited: true };\n }\n\n let deleteCount = first.end - first.start + 1;\n const prevBlank = first.start === 0 || (result[first.start - 1] ?? '').trim() === '';\n const nextBlank = (result[first.end + 1] ?? '').trim() === '';\n if (prevBlank && nextBlank && first.end + 1 < result.length) deleteCount++;\n result.splice(first.start, deleteCount);\n return { placed: false, edited: true };\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n const byModule = new Map<string, Set<string>>();\n for (let i = 0; i < lines.length; i++) {\n if (!/^from\\s+/.test(lines[i])) continue;\n\n let fullText = lines[i];\n if (fullText.includes('(') && !fullText.includes(')')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes(')')) break;\n }\n }\n\n const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n if (!match) continue;\n\n const mod = match[1];\n if (!byModule.has(mod)) byModule.set(mod, new Set());\n for (const id of match[2]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)) {\n byModule.get(mod)!.add(id);\n }\n }\n return byModule;\n}\n\n/**\n * Collected TypeScript imports grouped by form. Each map keys on the module\n * specifier (e.g. `./foo`, `node:fs`).\n */\ninterface TsImports {\n /** `import { X, Y } from 'module'` — module → identifier names. */\n named: Map<string, Set<string>>;\n /** `import type { X } from 'module'` — module → identifier names. */\n typeOnly: Map<string, Set<string>>;\n /** `import X from 'module'` or `import type X from 'module'` — module → name. */\n defaults: Map<string, string>;\n /** `import * as X from 'module'` — module → namespace alias name. */\n namespaces: Map<string, string>;\n /** `import 'module'` — modules imported for side effects only. */\n sideEffects: Set<string>;\n}\n\n/**\n * Collect TypeScript imports, grouped by form. Handles single-line and\n * multi-line `{ … }` named imports. Disjoint from Python's `from X import Y`\n * syntax so this can be called in parallel with `collectFromImports`.\n */\nfunction collectTsImports(lines: string[]): TsImports {\n const out: TsImports = {\n named: new Map(),\n typeOnly: new Map(),\n defaults: new Map(),\n namespaces: new Map(),\n sideEffects: new Set(),\n };\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!/^import(\\s|$)/.test(trimmed)) continue;\n\n // Accumulate multi-line `{ … }` imports.\n let fullText = lines[i];\n if (fullText.includes('{') && !fullText.includes('}')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes('}')) break;\n }\n }\n\n const normalized = fullText.replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n\n // `import 'module'`\n let m = normalized.match(/^import\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.sideEffects.add(m[1]);\n continue;\n }\n\n // `import * as X from 'module'`\n m = normalized.match(/^import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.namespaces.set(m[2], m[1]);\n continue;\n }\n\n // `import [Default,] { X, Y as Z } from 'module'` or `import type { X } from 'module'`\n m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n const isTypeOnly = !!m[1];\n const defaultName = m[2];\n const namesRaw = m[3];\n const mod = m[4];\n if (defaultName) out.defaults.set(mod, defaultName);\n const names = namesRaw\n .split(',')\n .map((s) => s.trim().replace(/\\s+as\\s+\\w+$/, ''))\n .filter(Boolean);\n for (const rawName of names) {\n const isInlineTypeOnly = rawName.startsWith('type ');\n const name = rawName.replace(/^type\\s+/, '');\n const target = isTypeOnly || isInlineTypeOnly ? out.typeOnly : out.named;\n if (!target.has(mod)) target.set(mod, new Set());\n target.get(mod)!.add(name);\n }\n continue;\n }\n\n // `import X from 'module'` or `import type X from 'module'`\n m = normalized.match(/^import\\s+(?:type\\s+)?(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.defaults.set(m[2], m[1]);\n continue;\n }\n }\n\n return out;\n}\n\n/**\n * Remove the given symbols from generated `import type` bindings, in place.\n *\n * Called when an existing *value* import for the same symbol is being spliced\n * back into the file. A value import satisfies both runtime and type uses, so\n * leaving the generated `import type { X }` would re-declare `X` (TS2300\n * duplicate identifier). Callers guarantee every symbol here is absent from\n * generated *value* imports, so each occurrence is type-only and safe to drop.\n *\n * Handles whole-line `import type { … }` and inline `import { …, type X }`,\n * single- or multi-line. A statement whose bindings all get stripped is\n * removed entirely.\n */\nfunction dropGeneratedTypeOnlyBindings(resultLines: string[], symbols: Set<string>): void {\n if (symbols.size === 0) return;\n const out: string[] = [];\n for (let i = 0; i < resultLines.length; i++) {\n const line = resultLines[i];\n const trimmed = line.trim();\n // Only named imports (with a brace) can carry the symbols we strip.\n if (!/^import\\b/.test(trimmed) || !trimmed.includes('{')) {\n out.push(line);\n continue;\n }\n // Gather the full (possibly multi-line) `{ … }` statement.\n const span = [line];\n while (!span.join(' ').includes('}') && i + 1 < resultLines.length) {\n i++;\n span.push(resultLines[i]);\n }\n const normalized = span.join(' ').replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n const m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+(['\"][^'\"]+['\"])$/);\n if (!m) {\n for (const s of span) out.push(s);\n continue;\n }\n const isTypeOnly = !!m[1];\n const defaultName = m[2];\n const items = m[3]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const modQuoted = m[4];\n const kept = items.filter((raw) => {\n const isTypeBinding = isTypeOnly || raw.startsWith('type ');\n const bare = raw.replace(/^type\\s+/, '');\n return !(isTypeBinding && symbols.has(bare));\n });\n if (kept.length === items.length) {\n // Nothing stripped — preserve the original lines verbatim.\n for (const s of span) out.push(s);\n continue;\n }\n if (kept.length === 0 && !defaultName) continue; // statement fully emptied\n const lead = line.match(/^(\\s*)/)?.[1] ?? '';\n const prefix = isTypeOnly ? 'import type ' : 'import ';\n const defaultPart = defaultName ? `${defaultName}, ` : '';\n out.push(`${lead}${prefix}${defaultPart}{ ${kept.join(', ')} } from ${modQuoted};`);\n }\n resultLines.splice(0, resultLines.length, ...out);\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles:\n *\n * - Python: `import X` and `from X import Y`\n * - TypeScript: `import { X } from 'module'`, `import type { X } from 'module'`,\n * `import X from 'module'`, `import * as X from 'module'`, `import 'module'`\n * - PHP: `use Foo\\Bar;` and `use Foo\\Bar as Baz;` (namespace-qualified only)\n * - Ruby: `require '…'` and `require_relative '…'`\n *\n * Mutates `resultLines` in place.\n */\nfunction filterOutIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\nfunction collectIgnoreRegionUsageText(lines: string[]): string {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n continue;\n }\n if (!skipping) continue;\n if (/^\\s*(import|from)\\s/.test(line)) continue;\n out.push(line);\n if (line.includes('@oagen-ignore-end')) skipping = false;\n }\n return out.join('\\n');\n}\n\nfunction removeDuplicateImportsCoveredByIgnoreBlocks(lines: string[]): void {\n const ignoredImports = new Set<string>();\n const importStatements = collectImportStatements(lines);\n for (const stmt of importStatements) {\n if (stmt.inIgnore) ignoredImports.add(normalizeImportStatement(stmt.lines));\n }\n if (ignoredImports.size === 0) return;\n\n for (const stmt of [...importStatements].reverse()) {\n if (stmt.inIgnore) continue;\n if (ignoredImports.has(normalizeImportStatement(stmt.lines))) {\n lines.splice(stmt.start, stmt.end - stmt.start + 1);\n }\n }\n}\n\nfunction collectImportStatements(\n lines: string[],\n): Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> {\n const statements: Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> = [];\n let inIgnore = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!inIgnore && line.includes('@oagen-ignore-start')) {\n inIgnore = true;\n continue;\n }\n if (inIgnore && line.includes('@oagen-ignore-end')) {\n inIgnore = false;\n continue;\n }\n if (!isImportLine(line)) continue;\n\n const start = i;\n let end = i;\n const statementLines = [line];\n const opens = (line.match(/[({]/g) ?? []).length;\n const closes = (line.match(/[)}]/g) ?? []).length;\n if (opens > closes) {\n while (end + 1 < lines.length) {\n end++;\n statementLines.push(lines[end]);\n if ((lines[end].match(/[)}]/g) ?? []).length > 0 && /\\bfrom\\b/.test(lines[end])) break;\n }\n i = end;\n }\n statements.push({ start, end, lines: statementLines, inIgnore });\n }\n return statements;\n}\n\nfunction normalizeImportStatement(lines: string[]): string {\n return lines.join('\\n').replace(/,\\s*}/g, ' }').replace(/\\s+/g, ' ').trim();\n}\n\nfunction isImportLine(line: string): boolean {\n const trimmed = line.trim();\n return (\n /^import(\\s|$)/.test(trimmed) ||\n /^from\\s+/.test(trimmed) ||\n /^use\\s+[\\w\\\\]/.test(trimmed) ||\n /^require(_relative)?\\s+['\"]/.test(trimmed)\n );\n}\n\nfunction identifierUsed(source: string, identifier: string): boolean {\n return new RegExp(`\\\\b${identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(source);\n}\n\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n // Imports inside @oagen-ignore regions are converted into normal imports\n // only when non-import ignore content still references them. This prevents\n // stale import-only ignore blocks from creating duplicate or unused imports.\n const existingOutsideIgnore = filterOutIgnoreRegions(existingLines);\n const ignoreRegionText = collectIgnoreRegionUsageText(existingLines);\n\n // Python-style `import hashlib`. Excludes TS forms like `import X from '…'`\n // (have a `from` clause) and TS multi-line type imports whose first line is\n // `import type {` (have a brace) — both are handled by the TS collector\n // below.\n const isPythonSimpleImport = (l: string) => /^import\\s+\\w/.test(l) && !/\\sfrom\\s/.test(l) && !/[{}]/.test(l);\n\n // Simple imports (import hashlib, import json, …)\n const existingSimple = new Set(existingOutsideIgnore.filter(isPythonSimpleImport).map((l) => l.trim()));\n const generatedSimple = new Set(resultLines.filter(isPythonSimpleImport).map((l) => l.trim()));\n const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n // From-imports — compare by module and find extra identifiers\n const existingFrom = collectFromImports(existingOutsideIgnore);\n const generatedFrom = collectFromImports(resultLines);\n\n // Build a set of all identifiers imported by the generated file (across all modules)\n // so we can detect when an existing barrel import's identifiers are covered by\n // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n const allGeneratedIds = new Set<string>();\n for (const ids of generatedFrom.values()) {\n for (const id of ids) allGeneratedIds.add(id);\n }\n\n const extraFromLines: string[] = [];\n for (const [mod, existIds] of existingFrom) {\n const genIds = generatedFrom.get(mod);\n if (!genIds) {\n // The exact module isn't in the generated file — but check whether every\n // identifier is already imported from a different (e.g., more-specific) module.\n const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n } else {\n const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n }\n }\n\n // TypeScript imports.\n const existingTs = collectTsImports(existingOutsideIgnore);\n const generatedTs = collectTsImports(resultLines);\n const extraTsLines: string[] = [];\n\n // Bindings the generated file imports anywhere, split by capability.\n //\n // `allGeneratedTsIds` — every binding regardless of module. The generator\n // frequently imports a symbol from a concrete file\n // (`./interfaces/connection.interface`) while the existing hand-written file\n // imported the same symbol from a barrel (`./interfaces`). Splicing the\n // barrel form back in would re-declare the binding (TS2300 duplicate\n // identifier), so a symbol already in scope satisfies a *type* use and is\n // never re-imported as a type even from a different specifier.\n //\n // `generatedValueIds` — only runtime-capable bindings (named / default /\n // namespace, never `import type`). A *value* use is satisfied only by one of\n // these: an `import type` binding is erased at compile time and cannot back a\n // runtime reference inside a preserved region. So a generated `import type`\n // must NOT suppress an existing value import of the same symbol.\n const allGeneratedTsIds = new Set<string>();\n const generatedValueIds = new Set<string>();\n for (const ids of generatedTs.named.values())\n for (const id of ids) {\n allGeneratedTsIds.add(id);\n generatedValueIds.add(id);\n }\n for (const ids of generatedTs.typeOnly.values()) for (const id of ids) allGeneratedTsIds.add(id);\n for (const name of generatedTs.defaults.values()) {\n allGeneratedTsIds.add(name);\n generatedValueIds.add(name);\n }\n for (const name of generatedTs.namespaces.values()) {\n allGeneratedTsIds.add(name);\n generatedValueIds.add(name);\n }\n\n // Symbols the generated file imports type-only that we are nonetheless\n // re-splicing as value imports (because a preserved region needs the runtime\n // binding). The spliced value import also covers the type use, so the\n // generated `import type` for the symbol must be dropped or the two collide\n // (TS2300). Collected during the loops below, applied just before splicing.\n const reclaimedValueIds = new Set<string>();\n const generatedHasValue = (id: string): boolean => generatedValueIds.has(id);\n const generatedHasTypeOnly = (id: string): boolean => allGeneratedTsIds.has(id) && !generatedValueIds.has(id);\n\n for (const mod of existingTs.sideEffects) {\n if (!generatedTs.sideEffects.has(mod)) extraTsLines.push(`import '${mod}';`);\n }\n for (const [mod, name] of existingTs.defaults) {\n if (generatedTs.defaults.has(mod)) continue;\n if (!identifierUsed(ignoreRegionText, name)) continue;\n if (generatedHasValue(name)) continue;\n if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n extraTsLines.push(`import ${name} from '${mod}';`);\n }\n for (const [mod, name] of existingTs.namespaces) {\n if (!identifierUsed(ignoreRegionText, name)) continue;\n if (generatedHasValue(name)) continue;\n if (generatedTs.namespaces.has(mod)) continue;\n if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n extraTsLines.push(`import * as ${name} from '${mod}';`);\n }\n for (const [mod, existIds] of existingTs.named) {\n const extra = [...existIds].filter((id) => !generatedHasValue(id) && identifierUsed(ignoreRegionText, id));\n for (const id of extra) if (generatedHasTypeOnly(id)) reclaimedValueIds.add(id);\n if (extra.length > 0) extraTsLines.push(`import { ${extra.join(', ')} } from '${mod}';`);\n }\n for (const [mod, existIds] of existingTs.typeOnly) {\n const extra = [...existIds].filter((id) => !allGeneratedTsIds.has(id) && identifierUsed(ignoreRegionText, id));\n if (extra.length > 0) extraTsLines.push(`import type { ${extra.join(', ')} } from '${mod}';`);\n }\n\n // Drop reclaimed symbols from generated `import type` lines so the value\n // imports spliced above do not duplicate them.\n dropGeneratedTypeOnlyBindings(resultLines, reclaimedValueIds);\n\n // PHP `use Foo\\Bar;` and `use Foo\\Bar as Baz;` — namespace-qualified only\n // (a backslash anywhere in the path) so this doesn't mistakenly hoist\n // single-segment in-class trait references like `use TraitName;`.\n const isPhpUseImport = (l: string) => /^use\\s+[\\w\\\\]+\\\\[\\w\\\\]*(\\s+as\\s+\\w+)?\\s*;?$/.test(l);\n const existingPhpUse = new Set(existingOutsideIgnore.filter(isPhpUseImport).map((l) => l.trim()));\n const generatedPhpUse = new Set(resultLines.filter(isPhpUseImport).map((l) => l.trim()));\n const extraPhpUse = [...existingPhpUse].filter((l) => !generatedPhpUse.has(l));\n\n // Ruby `require '...'` and `require_relative '...'`. Dedupe by (kind, path)\n // so quote style differs without producing duplicates — e.g. when the\n // emitter writes `require 'json'` but a Ruby formatter has rewritten the\n // on-disk copy to `require \"json\"`.\n const rubyRequireRe = /^(require(?:_relative)?)\\s+['\"]([^'\"]+)['\"]\\s*$/;\n const rubyRequireKey = (l: string): string | undefined => {\n const m = l.trim().match(rubyRequireRe);\n return m ? `${m[1]}\\t${m[2]}` : undefined;\n };\n const generatedRubyRequireKeys = new Set<string>();\n for (const l of resultLines) {\n const key = rubyRequireKey(l);\n if (key) generatedRubyRequireKeys.add(key);\n }\n const seenExistingKeys = new Set<string>();\n const extraRubyRequire: string[] = [];\n for (const l of existingOutsideIgnore) {\n const key = rubyRequireKey(l);\n if (!key) continue;\n if (generatedRubyRequireKeys.has(key)) continue;\n if (seenExistingKeys.has(key)) continue;\n seenExistingKeys.add(key);\n extraRubyRequire.push(l.trim());\n }\n\n const allExtra = [...extraSimple, ...extraFromLines, ...extraTsLines, ...extraPhpUse, ...extraRubyRequire];\n if (allExtra.length === 0) return;\n\n // Find last import line in resultLines (accounting for multiline imports).\n // Recognizes Python (`from X import Y`, `import X`), TS (`import …`), PHP\n // (`use …`), and Ruby (`require`, `require_relative`).\n const isImportStart = (l: string) =>\n /^\\s*import(\\s|$)/.test(l) ||\n /^from\\s+/.test(l) ||\n /^\\s*use\\s+[\\w\\\\]/.test(l) ||\n /^\\s*require(_relative)?\\s+['\"]/.test(l);\n let lastImportIdx = -1;\n for (let i = 0; i < resultLines.length; i++) {\n if (!isImportStart(resultLines[i])) continue;\n lastImportIdx = i;\n const opens = (resultLines[i].match(/[({]/g) ?? []).length;\n const closes = (resultLines[i].match(/[)}]/g) ?? []).length;\n if (opens > closes) {\n while (i + 1 < resultLines.length) {\n i++;\n lastImportIdx = i;\n if ((resultLines[i].match(/[)}]/g) ?? []).length > 0) break;\n }\n }\n }\n\n if (lastImportIdx >= 0) {\n resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n return;\n }\n\n // No import survived in the generated file (e.g. its only import was a\n // type-only line reclaimed above). Insert after any leading comment header\n // so the spliced imports still land at the top of the file.\n let insertAt = 0;\n let inBlockComment = false;\n for (let i = 0; i < resultLines.length; i++) {\n const t = resultLines[i].trim();\n if (inBlockComment) {\n insertAt = i + 1;\n if (t.includes('*/')) inBlockComment = false;\n continue;\n }\n if (t.startsWith('//')) {\n insertAt = i + 1;\n continue;\n }\n if (t.startsWith('/*')) {\n insertAt = i + 1;\n inBlockComment = !t.includes('*/');\n continue;\n }\n break; // first blank or code line — stop here\n }\n resultLines.splice(insertAt, 0, ...allExtra);\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\n\nexport function buildEmitterContext(\n spec: ApiSpec,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n scopedServices?: Set<string>;\n },\n): EmitterContext {\n const resolvedOperations = resolveOperations(spec, options.operationHints, options.mountRules);\n\n // In a scoped run, derive the model/enum allow-lists = names reachable\n // from the SELECTED source services (those whose post-mount target is selected).\n // Emitters write a model/enum FILE only when it is in these sets, so a\n // non-selected service's exclusive models are left untouched (no leak) while\n // shared models reachable from the selection still emit. Barrels stay full.\n let scopedModelNames: Set<string> | undefined;\n let scopedEnumNames: Set<string> | undefined;\n if (options.scopedServices && options.scopedServices.size > 0) {\n const selected = options.scopedServices;\n const selectedSourceServices = spec.services.filter((s) =>\n resolvedOperations.some((r) => r.service.name === s.name && selected.has(r.mountOn)),\n );\n const reachable = collectReferencedNames(selectedSourceServices, spec.models, { preserveAllDiscriminated: false });\n scopedModelNames = reachable.models;\n scopedEnumNames = reachable.enums;\n }\n\n return {\n namespace: toSnakeCase(options.namespace),\n namespacePascal: options.namespace,\n spec,\n outputDir: options.outputDir,\n apiSurface: options.apiSurface,\n overlayLookup: options.overlayLookup,\n resolvedOperations,\n modelHints: options.modelHints,\n emitterOptions: options.emitterOptions,\n targetDir: options.target,\n priorTargetManifestPaths: options.priorTargetManifestPaths,\n scopedServices: options.scopedServices,\n scopedModelNames,\n scopedEnumNames,\n };\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n services: Service[],\n models: Model[],\n opts: { preserveAllDiscriminated?: boolean } = {},\n): { models: Set<string>; enums: Set<string> } {\n // Default: preserve EVERY discriminated/event model as public surface (full\n // emission). Strict mode (`preserveAllDiscriminated: false`, used to compute a\n // scoped run's reachable set) skips that blanket and instead chases the mapping\n // variants of discriminated models that are actually reached — so a scoped\n // service doesn't pull in the entire unrelated event tree.\n const preserveAllDiscriminated = opts.preserveAllDiscriminated !== false;\n const referencedModels = new Set<string>();\n const referencedEnums = new Set<string>();\n\n const collectFromTypeRef = (ref: TypeRef): void => {\n walkTypeRef(ref, {\n model: (r) => referencedModels.add(r.name),\n enum: (r) => referencedEnums.add(r.name),\n });\n };\n\n // Seed: walk every operation's params, request body, response, errors, and pagination\n for (const service of services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectFromTypeRef(p.type);\n }\n if (op.requestBody) collectFromTypeRef(op.requestBody);\n collectFromTypeRef(op.response);\n if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n for (const err of op.errors) {\n if (err.type) collectFromTypeRef(err.type);\n }\n if (op.successResponses) {\n for (const sr of op.successResponses) {\n collectFromTypeRef(sr.type);\n }\n }\n }\n }\n\n // Preserve discriminated models as public SDK types even when no operation\n // returns them directly. This matters for event/webhook unions where the base\n // operation references a generic envelope but the variant structs are still\n // useful public surface.\n //\n // Also preserve the variants mapped from an `allOf [base, oneOf […]]` base\n // (carried as `Model.discriminator.mapping`). The base model is reached\n // through the operation; without explicitly chasing its mapping, the\n // variant structs would be unreachable and the dispatcher would dangle\n // imports.\n if (preserveAllDiscriminated) {\n for (const model of models) {\n if (isDiscriminatedModel(model)) {\n referencedModels.add(model.name);\n }\n const disc = model.discriminator;\n if (disc?.mapping) {\n for (const variantName of Object.values(disc.mapping)) {\n referencedModels.add(variantName);\n }\n }\n }\n }\n\n // Chase: transitively resolve model field references until stable\n const modelsByName = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const queue = [...referencedModels];\n while (queue.length > 0) {\n const name = queue.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const model = modelsByName.get(name);\n if (!model) continue;\n // A reached discriminated base pulls in its mapping variants (the dispatcher\n // would otherwise dangle). In full mode this is redundant with the blanket\n // pass above; in strict mode it is the only path that includes variants.\n const disc = model.discriminator;\n if (disc?.mapping) {\n for (const variantName of Object.values(disc.mapping)) {\n if (!referencedModels.has(variantName)) {\n referencedModels.add(variantName);\n queue.push(variantName);\n }\n }\n }\n for (const field of model.fields) {\n collectFromTypeRef(field.type);\n // If new models were discovered, enqueue them\n for (const m of referencedModels) {\n if (!visited.has(m)) queue.push(m);\n }\n }\n }\n\n return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n return model.fields.some(\n (field) =>\n (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n );\n}\n\n/**\n * Collect all generated files from an emitter (no headers, no path prefixes).\n *\n * In a scoped (`--services`) run the spec is NOT filtered: every generator runs\n * over the full spec so model placement, dedup, the root client, and all\n * aggregate/barrel files are byte-identical to a full run (and a brand-new\n * selected service is wired into the client automatically). The emitters\n * themselves consult `ctx.scopedServices` to emit only the selected services'\n * per-service resource/test files.\n */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n const referenced = collectReferencedNames(spec.services, spec.models);\n const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n const reachableSpec: ApiSpec = { ...spec, models: reachableModels, enums: reachableEnums };\n\n return [\n ...emitter.generateModels(reachableModels, ctx),\n ...emitter.generateEnums(reachableEnums, ctx),\n ...emitter.generateResources(spec.services, ctx),\n ...emitter.generateClient(spec, ctx),\n ...emitter.generateErrors(ctx),\n ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n ...emitter.generateTests(reachableSpec, ctx),\n ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n return files.map((f) => ({\n ...f,\n content:\n !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n skipIfExists: f.skipIfExists ?? false,\n }));\n}\n\nexport function generateFiles(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n /** Scoped-generation signal (POST-MOUNT names); set on ctx for emitters to gate per-service emission. */\n scopedServices?: Set<string>;\n },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n const ctx = buildEmitterContext(spec, options);\n const files = generateAllFiles(spec, emitter, ctx);\n const operations = emitter.buildOperationsMap?.(spec, ctx);\n const header = emitter.fileHeader();\n return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Validate a `--services` selection and return it as a set of POST-MOUNT service\n * names for emitters to scope on.\n *\n * Scoped generation does NOT filter the IR: model placement, dedup/aliasing, and\n * shared-schema decisions are global computations over the full service/model set\n * (filtering them churns shared `common/` files). Instead the full spec flows to\n * the emitters unchanged and this set is passed as `ctx.scopedServices`; each\n * emitter gates only its per-service resource/test emission on it.\n *\n * Matching is on the POST-MOUNT name. Mount resolution never mutates\n * `spec.services` — the post-mount target lives on `ResolvedOperation.mountOn`\n * (`mountOn = hint?.mountOn ?? mountRules[service.name] ?? service.name`) — so the\n * post-mount name of a source service is derived here as\n * `mountRules[service.name] ?? service.name`. Selecting a target (e.g.\n * `DirectorySync`) is valid because every source tag that mounts into it\n * (`DirectoryUsers`, `DirectoryGroups`, …) shares that post-mount name, and the\n * emitters group resources by mount, so all siblings emit together.\n *\n * @param spec - The parsed API spec (never mutated; never filtered).\n * @param selected - Post-mount service names from `--services` (normalized/trimmed).\n * @param mountRules - Source-service-name → post-mount-target mappings.\n * @returns The validated selection as a `Set` of post-mount names.\n * @throws A `ConfigError` listing valid post-mount names when a selection is\n * unknown — scoped generation never silently emits the wrong set.\n */\nexport function resolveScopedServices(\n spec: ApiSpec,\n selected: string[],\n mountRules?: Record<string, string>,\n): Set<string> {\n const mounts = mountRules ?? {};\n const postMountName = (name: string): string => mounts[name] ?? name;\n const validPostMount = new Set(spec.services.map((s) => postMountName(s.name)));\n const selectedSet = new Set(selected);\n\n const unknown = [...selectedSet].filter((s) => !validPostMount.has(s));\n if (unknown.length > 0) {\n const err = new Error(\n `Unknown --services: ${unknown.sort().join(', ')}. ` +\n `Valid post-mount services: ${[...validPostMount].sort().join(', ')}`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n\n return selectedSet;\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path. Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n fromFilePath: string,\n importModulePath: string,\n knownPaths: Set<string>,\n): string | undefined {\n // Strip quotes from module path key (tree-sitter keeps them)\n const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n // Skip non-relative imports (node_modules, bare specifiers)\n if (!cleaned.startsWith('.')) return undefined;\n\n const dir = path.dirname(fromFilePath);\n const resolved = path.normalize(path.join(dir, cleaned));\n\n // Try exact match, .ts, /index.ts\n for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n if (knownPaths.has(candidate)) return candidate;\n }\n return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target. Roots are entry points from which we trace\n * the import graph. Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n // Fixtures are never roots (and should be filtered by integrateTarget already)\n if (filePath.includes('/fixtures/')) return false;\n // Test files are roots — they are standalone entry points that belong in the\n // target repo even though nothing imports them.\n if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n // Serializer files\n if (filePath.includes('/serializers/')) return false;\n // Standalone interface files (not barrel/index)\n if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points. Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n if (!hasGrammar(language)) return files;\n\n const knownPaths = new Set(files.map((f) => f.path));\n\n // Build dependency graph: file → set of files it imports\n const deps = new Map<string, Set<string>>();\n for (const file of files) {\n // Only parse .ts/.js files (skip JSON, etc.)\n if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n deps.set(file.path, new Set());\n continue;\n }\n const parsed = await extractStatements(file.content, language);\n const fileDeps = new Set<string>();\n for (const imp of parsed.imports) {\n const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n // Also check re-export statements (export * from './foo')\n for (const stmt of parsed.statements) {\n if (stmt.kind === 'reexport') {\n // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n if (match) {\n const resolved = resolveImportPath(file.path, match[1], knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n }\n }\n deps.set(file.path, fileDeps);\n }\n\n // Determine which file extensions are source code for this language\n const codeExtensions = new Set([\n '.ts',\n '.js',\n '.tsx',\n '.jsx',\n '.py',\n '.rb',\n '.go',\n '.rs',\n '.kt',\n '.cs',\n '.ex',\n '.exs',\n '.php',\n ]);\n\n // BFS from roots\n const reachable = new Set<string>();\n const queue: string[] = [];\n for (const file of files) {\n const ext = file.path.slice(file.path.lastIndexOf('.'));\n // Non-code files (JSON, etc.) are always reachable — they can't participate\n // in the import graph and are loaded at runtime (e.g. test fixtures).\n if (!codeExtensions.has(ext)) {\n reachable.add(file.path);\n continue;\n }\n if (isRootFile(file.path)) {\n reachable.add(file.path);\n queue.push(file.path);\n }\n }\n while (queue.length > 0) {\n const current = queue.pop()!;\n const fileDeps = deps.get(current);\n if (!fileDeps) continue;\n for (const dep of fileDeps) {\n if (!reachable.has(dep)) {\n reachable.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n const langPrefix = `${language}/`;\n return files\n .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n .map((f) => {\n const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n return {\n ...f,\n skipIfExists: false, // Always merge in target — never hard-skip\n path: stripped,\n };\n });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`. This preserves backward-compatible imports\n * (e.g., `from acme.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n files: GeneratedFile[],\n targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n const result = [...files];\n const removals: string[] = [];\n\n for (let i = 0; i < result.length; i++) {\n const file = result[i];\n // Match package init files: e.g., src/acme/api_keys/__init__.py\n const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n if (!match) continue;\n\n const dirPath = match[1]; // e.g., src/acme/api_keys\n const moduleFilePath = `${dirPath}.py`; // e.g., src/acme/api_keys.py\n const fullModulePath = path.join(targetDir, moduleFilePath);\n\n let moduleContent: string;\n try {\n moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n } catch {\n continue; // Module file doesn't exist — no conflict\n }\n\n // Create a compat shim inside the package with the old module's content\n const compatPath = `${dirPath}/_compat.py`;\n result.push({\n path: compatPath,\n content: moduleContent,\n overwriteExisting: true,\n });\n\n // Append re-export from _compat to __init__.py so existing imports work.\n // Compat must come AFTER generated models so hand-written types take\n // precedence over generated types with the same name.\n const compatImport = 'from ._compat import * # noqa: F401,F403 # pyright: ignore[reportUnusedImport]';\n const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n result[i] = {\n ...file,\n content: existingContent + compatImport + '\\n',\n };\n\n // Schedule the shadowed module file for removal\n removals.push(fullModulePath);\n }\n\n return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n files: GeneratedFile[];\n language: string;\n targetDir: string;\n header: string;\n}): Promise<IntegrateResult> {\n const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n const shaken = await treeShakeFiles(mapped, opts.language);\n\n // Handle file-to-directory conflicts before writing\n const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n const result = await writeFiles(resolved, opts.targetDir, {\n language: opts.language,\n header: opts.header,\n });\n\n // Remove shadowed module files after integration\n for (const filePath of removals) {\n try {\n await fs.unlink(filePath);\n } catch {\n // File may already be gone\n }\n }\n\n // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n // Tree-shaking decides what to write, but shaken files are still oagen-managed\n // and must not be pruned from the target on subsequent runs.\n return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n if (!emitter.formatCommand) return;\n\n const formatCmd = emitter.formatCommand(targetDir);\n if (!formatCmd) return;\n\n const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n const batchSize = formatCmd.batchSize ?? 100;\n\n process.stderr.write(\n `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n );\n\n for (let i = 0; i < absolutePaths.length; i += batchSize) {\n const batch = absolutePaths.slice(i, i + batchSize);\n try {\n await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n cwd: targetDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 120_000,\n });\n } catch (err) {\n // Formatter failed on this batch — continue with remaining batches.\n // Surface the failure on stderr so misconfigured commands don't silently\n // leave generated code unformatted every regen.\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n }\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir). On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n * - The manifest is versioned so future format changes can be handled safely.\n * - Paths are stored sorted for deterministic diffs in git.\n * - Deletion is gated on a header guard when one is available: we only remove\n * files whose contents start with the auto-generated header. This protects\n * a hand-maintained file that happens to share a name with a previously\n * generated one (extremely rare, but worth catching).\n * - On first adoption (no previous manifest), pruning is skipped and a\n * one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n /** Schema version. Bump when the format changes incompatibly. */\n version: number;\n /** Emitter language (e.g. \"python\"). Used only as a consistency hint. */\n language: string;\n /** Human-readable or package-level SDK identity (e.g. \"acme-php\"). */\n sdkName?: string;\n /** ISO-8601 timestamp of the run that produced the current manifest contents. */\n generatedAt: string;\n /** SHA-256 hash of the source OpenAPI spec used for generation. */\n specSha?: string;\n /** Path or reference to the source spec. */\n specPath?: string;\n /** Git SHA or version of the emitter code used. */\n emitterSha?: string;\n /** Emitter version string if available. */\n emitterVersion?: string;\n /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n configSha?: string;\n /** Version of the compat snapshot/report schema expected by this generation. */\n compatSchemaVersion?: string;\n /** Sorted list of paths, relative to the manifest's containing directory. */\n files: string[];\n /** Maps \"METHOD /path\" to SDK method + service property name. */\n operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n /** Paths actually deleted. */\n pruned: string[];\n /** Paths skipped because the header guard didn't match (preserved). */\n preserved: string[];\n /** Paths already absent on disk (nothing to do). */\n missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory. Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<Manifest>;\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.language !== 'string' ||\n typeof parsed.generatedAt !== 'string' ||\n !Array.isArray(parsed.files) ||\n !parsed.files.every((p): p is string => typeof p === 'string')\n ) {\n return null;\n }\n if (parsed.version > MANIFEST_VERSION) {\n console.warn(\n `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n );\n return null;\n }\n // v1 manifests are forward-compatible — new fields are simply absent\n return parsed as Manifest;\n } catch {\n return null;\n }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n language: string;\n files: Iterable<string>;\n sdkName?: string;\n specSha?: string;\n specPath?: string;\n emitterSha?: string;\n emitterVersion?: string;\n configSha?: string;\n compatSchemaVersion?: string;\n operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n const manifest: Manifest = {\n version: MANIFEST_VERSION,\n language: opts.language,\n ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n generatedAt: new Date().toISOString(),\n ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n files: [...new Set(opts.files)].sort(),\n ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n };\n const previous = await readManifest(dir);\n if (previous && sameManifestExceptGeneratedAt(previous, manifest)) {\n manifest.generatedAt = previous.generatedAt;\n }\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\nfunction sameManifestExceptGeneratedAt(a: Manifest, b: Manifest): boolean {\n const { generatedAt: _aGeneratedAt, ...aComparable } = a;\n const { generatedAt: _bGeneratedAt, ...bComparable } = b;\n return JSON.stringify(aComparable) === JSON.stringify(bComparable);\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n const current = new Set(currentPaths);\n return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Merge a scoped run's emitted records into the prior manifest's records.\n *\n * A scoped (`--services`) run only emits files for the selected services, but it\n * must NOT discard the prior manifest's record of unselected services' files\n * records. The result unions prior + scoped file paths and shallow-merges the\n * operations maps, with scoped operations overriding prior entries for the same\n * \"METHOD /path\" key (a re-emission updates that operation's record).\n *\n * When `prev` is null (the first-ever run is scoped) there is nothing to\n * preserve, so the scoped subset is returned unchanged — matching the\n * first-adoption behavior of a full run.\n */\nexport function mergeScopedManifestRecords(\n prev: Manifest | null,\n scopedFiles: Iterable<string>,\n scopedOperations?: Record<string, unknown>,\n): { files: string[]; operations?: Record<string, unknown> } {\n const scopedFileList = [...scopedFiles];\n if (!prev) {\n return { files: scopedFileList, operations: scopedOperations };\n }\n const files = [...new Set([...prev.files, ...scopedFileList])].sort();\n const priorOps = prev.operations;\n const operations = priorOps || scopedOperations ? { ...priorOps, ...scopedOperations } : undefined;\n return { files, operations };\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered. When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting. Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n dir: string,\n paths: string[],\n opts: { header?: string } = {},\n): Promise<PruneResult> {\n const pruned: string[] = [];\n const preserved: string[] = [];\n const missing: string[] = [];\n\n for (const relPath of paths) {\n const fullPath = path.join(dir, relPath);\n let content: string;\n try {\n content = await fs.readFile(fullPath, 'utf-8');\n } catch {\n missing.push(relPath);\n continue;\n }\n if (opts.header && !content.startsWith(opts.header)) {\n preserved.push(relPath);\n continue;\n }\n try {\n await fs.unlink(fullPath);\n pruned.push(relPath);\n } catch {\n // Racing deletion or permission issue — treat as missing rather than fatal.\n missing.push(relPath);\n continue;\n }\n await removeEmptyParents(path.dirname(fullPath), dir);\n }\n\n return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory. Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n let current = path.resolve(startDir);\n const stop = path.resolve(stopDir);\n while (current.startsWith(stop + path.sep) && current !== stop) {\n let entries: string[];\n try {\n entries = await fs.readdir(current);\n } catch {\n return;\n }\n if (entries.length > 0) return;\n try {\n await fs.rmdir(current);\n } catch {\n return;\n }\n current = path.dirname(current);\n }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { resolveScopedServices } from './scoped-services.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport {\n computeStalePaths,\n MANIFEST_FILENAME,\n mergeScopedManifestRecords,\n pruneStaleFiles,\n readManifest,\n writeManifest,\n} from './manifest.js';\n\nexport async function generate(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n dryRun?: boolean;\n outputDir: string;\n target?: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n noPrune?: boolean;\n /**\n * Post-mount service names to generate (a `--services` run). When non-empty,\n * the FULL spec is still emitted for models/enums/client/barrels (so shared\n * files stay byte-identical and a brand-new selected service is wired into the\n * client automatically); only per-service resource/test emission is gated to\n * the selection (via `ctx.scopedServices`). Pruning is disabled and the\n * manifest is merged so unselected services' records survive.\n */\n services?: string[];\n },\n): Promise<GeneratedFile[]> {\n // Scoped generation: validate + expand the selection to POST-MOUNT names. The\n // spec is NOT filtered — placement/dedup/shared-schemas are computed over the\n // full spec so shared files stay byte-identical; emitters gate only per-service\n // resource/test emission on this set.\n const scopedServices =\n options.services && options.services.length > 0\n ? resolveScopedServices(spec, options.services, options.mountRules)\n : undefined;\n const scoped = scopedServices !== undefined;\n // Scoped mode implies no-prune so unselected services' files survive.\n const noPrune = options.noPrune === true || scoped;\n\n // Read previous manifests up front so emitters can mark files the prior run\n // wrote as safe-to-overwrite (vs files a human hand-maintains), and so scoped\n // runs can merge prior records. Skipped only when --no-prune is set on a\n // non-scoped run (opting out of lifecycle tracking). Scoped runs always read,\n // even though they force no-prune, because the merge needs the prior records.\n const skipManifestRead = options.noPrune === true && !scoped;\n const outputPrevManifestForCtx = skipManifestRead ? null : await readManifest(options.outputDir);\n const targetManifestForCtx = options.target && !skipManifestRead ? await readManifest(options.target) : null;\n const priorTargetManifestPaths = targetManifestForCtx\n ? new Set(targetManifestForCtx.files)\n : outputPrevManifestForCtx\n ? new Set(outputPrevManifestForCtx.files)\n : undefined;\n\n const {\n files: withHeaders,\n header,\n operations,\n } = generateFiles(spec, emitter, {\n ...options,\n priorTargetManifestPaths,\n scopedServices,\n });\n\n if (options.dryRun) {\n if (options.target) {\n console.log(`\\nTarget integration (${options.target}):`);\n for (const f of withHeaders) {\n console.log(` ${f.path}`);\n }\n }\n return withHeaders;\n }\n\n // Reuse the manifest read before generation; nothing above writes it.\n const outputPrevManifest = outputPrevManifestForCtx;\n\n const writeResult = await writeFiles(withHeaders, options.outputDir, {\n language: emitter.language,\n header,\n });\n\n if (writeResult.merged.length > 0) {\n console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n }\n if (writeResult.ignored.length > 0) {\n console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n }\n\n const outputEmittedPaths = withHeaders.map((f) => f.path);\n await applyManifestPrune({\n dir: options.outputDir,\n label: 'Output',\n prevManifest: outputPrevManifest,\n currentPaths: outputEmittedPaths,\n language: emitter.language,\n header,\n noPrune,\n operations,\n scoped,\n });\n\n // Format output files so the emitter's formatter runs even without --target.\n const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n if (allOutputFiles.length > 0) {\n await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n }\n\n // Target integration pass\n if (options.target) {\n // Reuse the manifest we already read to build the emitter context. This\n // is correct because nothing between the two reads writes the manifest.\n const targetPrevManifest = targetManifestForCtx;\n\n const targetResult = await integrateGeneratedFiles({\n files: withHeaders,\n language: emitter.language,\n targetDir: options.target,\n header,\n });\n\n if (targetResult.written.length > 0) {\n console.log(`Target: created ${targetResult.written.length} new files`);\n }\n if (targetResult.merged.length > 0) {\n console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n }\n if (targetResult.skipped.length > 0) {\n console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n }\n\n await applyManifestPrune({\n dir: options.target,\n label: 'Target',\n prevManifest: targetPrevManifest,\n currentPaths: targetResult.emittedPaths,\n language: emitter.language,\n header,\n noPrune,\n operations,\n scoped,\n });\n\n // Run the emitter's formatter on all written/merged/identical files\n const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n if (allTargetFiles.length > 0) {\n await formatTargetFiles(emitter, options.target, allTargetFiles);\n }\n }\n\n return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest. Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n dir: string;\n label: string;\n prevManifest: Awaited<ReturnType<typeof readManifest>>;\n currentPaths: string[];\n language: string;\n header: string;\n noPrune?: boolean;\n operations?: Record<string, unknown>;\n /** When true, union this scoped run's records with the prior manifest. */\n scoped?: boolean;\n}): Promise<void> {\n // A scoped run only emits the selected services' files, so the manifest is\n // merged with the prior records rather than replaced — otherwise unselected\n // services would be dropped from the manifest and mis-pruned on the next run.\n const records = opts.scoped\n ? mergeScopedManifestRecords(opts.prevManifest, opts.currentPaths, opts.operations)\n : { files: opts.currentPaths, operations: opts.operations };\n const manifestOpts = { language: opts.language, files: records.files, operations: records.operations };\n if (opts.noPrune) {\n // Still refresh the manifest so future runs with pruning enabled have a baseline.\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n if (!opts.prevManifest) {\n console.log(\n `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n );\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n if (stale.length > 0) {\n const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n if (pruned.length > 0) {\n console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n }\n if (preserved.length > 0) {\n console.log(\n `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n );\n for (const p of preserved) console.log(` ${p}`);\n }\n }\n\n await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n const emitter = emitters.get(language);\n if (!emitter) {\n const available = [...emitters.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `Unknown language: ${language}. Available: ${available}`,\n `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n );\n }\n return emitter;\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n switch (kind) {\n case 'field-added':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'field-removed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-type-changed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-format-changed':\n // A primitive's `format` changing (e.g., string → string format=email)\n // is classified additive at the IR level: the wire-format base type is\n // unchanged, so callers' deserialization keeps working. Per-emitter\n // compat checks catch any source-level break a specific language layers\n // on top (e.g., a typed Email value object in TypeScript).\n return { kind, fieldName, classification: 'additive' };\n case 'field-required-changed':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n details: isRequired ? 'optional → required' : 'required → optional',\n };\n case 'field-access-changed':\n return { kind, fieldName, classification: 'breaking' };\n }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n switch (kind) {\n case 'param-added':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-removed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-type-changed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-format-changed':\n // See `field-format-changed`: format-only diffs are additive at the IR\n // layer.\n return { kind, paramName, classification: 'additive' };\n case 'param-required-changed':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-default-changed':\n // Removing or changing a default that callers may have implicitly relied on\n // changes runtime behavior for clients who never set the param explicitly.\n // We treat this as breaking so it surfaces as a major bump rather than\n // sliding through as a silent regression.\n return { kind, paramName, classification: 'breaking' };\n }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'model-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newModel] of newByName) {\n const oldModel = oldByName.get(name);\n if (!oldModel) continue;\n\n const fieldChanges = diffFields(oldModel, newModel);\n if (fieldChanges.length > 0) {\n const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n changes.push({\n kind: 'model-modified',\n name,\n fieldChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n const changes: FieldChange[] = [];\n const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n for (const [name, field] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyFieldChange('field-added', name, field.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyFieldChange('field-removed', name));\n }\n }\n\n for (const [name, newField] of newByName) {\n const oldField = oldByName.get(name);\n if (!oldField) continue;\n\n if (!typeRefsEqual(oldField.type, newField.type)) {\n if (primitivesDifferOnlyByFormat(oldField.type, newField.type)) {\n changes.push({\n ...classifyFieldChange('field-format-changed', name),\n details: formatChangeDetails(oldField.type, newField.type),\n });\n } else {\n changes.push({\n kind: 'field-type-changed',\n fieldName: name,\n classification: 'breaking',\n details: `type changed`,\n });\n }\n }\n\n if (oldField.required !== newField.required) {\n changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n }\n\n if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n changes.push(classifyFieldChange('field-access-changed', name));\n }\n }\n\n return changes;\n}\n\n/**\n * True when both refs are primitives with the same base `type` but different\n * `format`. Used to downgrade format-only diffs from breaking type changes to\n * additive `field-format-changed` / `param-format-changed` events: the wire\n * base type is unchanged, so the diff is a hint to language emitters rather\n * than a source-level break.\n */\nexport function primitivesDifferOnlyByFormat(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== 'primitive' || b.kind !== 'primitive') return false;\n if (a.type !== b.type) return false;\n return (a.format ?? '') !== (b.format ?? '');\n}\n\nexport function formatChangeDetails(a: TypeRef, b: TypeRef): string {\n const oldFmt = a.kind === 'primitive' ? a.format : undefined;\n const newFmt = b.kind === 'primitive' ? b.format : undefined;\n return `format ${oldFmt ?? '<unset>'} → ${newFmt ?? '<unset>'}`;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== b.kind) return false;\n\n switch (a.kind) {\n case 'primitive':\n return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n case 'array':\n return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n case 'model':\n return b.kind === 'model' && a.name === b.name;\n case 'enum':\n return b.kind === 'enum' && a.name === b.name;\n case 'literal':\n return b.kind === 'literal' && a.value === b.value;\n case 'nullable':\n return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n case 'union': {\n if (b.kind !== 'union') return false;\n if (a.variants.length !== b.variants.length) return false;\n if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n // Compare discriminator\n if (!a.discriminator && !b.discriminator) return true;\n if (!a.discriminator || !b.discriminator) return false;\n if (a.discriminator.property !== b.discriminator.property) return false;\n const aKeys = Object.keys(a.discriminator.mapping).sort();\n const bKeys = Object.keys(b.discriminator.mapping).sort();\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n }\n case 'map':\n return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n }\n return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { formatChangeDetails, primitivesDifferOnlyByFormat, typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({\n kind: 'operation-added',\n serviceName,\n operationName: name,\n classification: 'additive',\n });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({\n kind: 'operation-removed',\n serviceName,\n operationName: name,\n classification: 'breaking',\n });\n }\n }\n\n for (const [name, newOp] of newByName) {\n const oldOp = oldByName.get(name);\n if (!oldOp) continue;\n\n const paramChanges = diffParams(oldOp, newOp);\n const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n const pathChanged = oldOp.path !== newOp.path;\n const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n const errorsChanged = errorsDiff !== 'none';\n\n const hasChanges =\n paramChanges.length > 0 ||\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedChanged ||\n injectIdempotencyKeyChanged ||\n errorsChanged;\n\n if (hasChanges) {\n // paginated: false→true is additive (SDK gains pagination helper)\n // paginated: true→false is breaking (SDK loses pagination helper)\n const paginatedBreaking = paginatedChanged && !newOp.pagination;\n // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n const errorsBreaking = errorsDiff === 'breaking';\n\n const hasBreaking =\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedBreaking ||\n injectIdempotencyKeyBreaking ||\n errorsBreaking ||\n paramChanges.some((pc) => pc.classification === 'breaking');\n changes.push({\n kind: 'operation-modified',\n serviceName,\n operationName: name,\n paramChanges,\n responseChanged,\n requestBodyChanged,\n httpMethodChanged,\n pathChanged,\n paginatedChanged,\n injectIdempotencyKeyChanged,\n errorsChanged,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n oldErrors: ErrorResponse[],\n newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n let hasAdditive = false;\n let hasBreaking = false;\n\n // New error codes added → additive (SDK gains new error classes)\n for (const code of newByCode.keys()) {\n if (!oldByCode.has(code)) hasAdditive = true;\n }\n\n // Old error codes removed → breaking (SDK loses error classes)\n for (const code of oldByCode.keys()) {\n if (!newByCode.has(code)) hasBreaking = true;\n }\n\n // Shared error codes with changed types → breaking\n for (const [code, newErr] of newByCode) {\n const oldErr = oldByCode.get(code);\n if (!oldErr) continue;\n if (!oldErr.type && !newErr.type) continue;\n if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n hasBreaking = true;\n }\n }\n\n if (hasBreaking) return 'breaking';\n if (hasAdditive) return 'additive';\n return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n const changes: ParamChange[] = [];\n const tagged = (loc: 'path' | 'query' | 'header', params: typeof oldOp.queryParams) =>\n params.map((p) => ({ p, loc }));\n const allOldParams = [\n ...tagged('path', oldOp.pathParams),\n ...tagged('query', oldOp.queryParams),\n ...tagged('header', oldOp.headerParams),\n ];\n const allNewParams = [\n ...tagged('path', newOp.pathParams),\n ...tagged('query', newOp.queryParams),\n ...tagged('header', newOp.headerParams),\n ];\n const oldByName = new Map(allOldParams.map((e) => [e.p.name, e]));\n const newByName = new Map(allNewParams.map((e) => [e.p.name, e]));\n\n for (const [name, entry] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyParamChange('param-added', name, entry.p.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyParamChange('param-removed', name));\n }\n }\n\n for (const [name, newEntry] of newByName) {\n const oldEntry = oldByName.get(name);\n if (!oldEntry) continue;\n\n if (!typeRefsEqual(oldEntry.p.type, newEntry.p.type)) {\n if (primitivesDifferOnlyByFormat(oldEntry.p.type, newEntry.p.type)) {\n const change = classifyParamChange('param-format-changed', name);\n change.details = formatChangeDetails(oldEntry.p.type, newEntry.p.type);\n changes.push(change);\n } else {\n changes.push(classifyParamChange('param-type-changed', name));\n }\n }\n\n if (oldEntry.p.required !== newEntry.p.required) {\n changes.push(classifyParamChange('param-required-changed', name, newEntry.p.required));\n }\n\n const oldDefault = serializeDefault(oldEntry.p.default);\n const newDefault = serializeDefault(newEntry.p.default);\n if (oldDefault !== newDefault) {\n const change = classifyParamChange('param-default-changed', name);\n change.oldDefault = oldDefault;\n change.newDefault = newDefault;\n change.paramLocation = newEntry.loc;\n change.details = `default ${oldDefault ?? '<unset>'} → ${newDefault ?? '<unset>'}`;\n changes.push(change);\n }\n }\n\n return changes;\n}\n\nfunction serializeDefault(value: unknown): string | null {\n if (value === undefined) return null;\n if (value === null) return 'null';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n // Objects/arrays: stable JSON. Stringification of equal-valued objects is\n // deterministic enough for this comparison since callers typically pass\n // primitives; complex defaults are rare.\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'service-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newService] of newByName) {\n const oldService = oldByName.get(name);\n if (!oldService) continue;\n\n changes.push(...diffOperations(name, oldService.operations, newService.operations));\n }\n\n return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { BehaviorChange, Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n const changes: Change[] = [\n ...diffModels(oldSpec.models, newSpec.models),\n ...diffEnums(oldSpec.enums, newSpec.enums),\n ...diffServices(oldSpec.services, newSpec.services),\n ];\n\n const behaviorChanges = collectBehaviorChanges(changes);\n\n return {\n oldVersion: oldSpec.version,\n newVersion: newSpec.version,\n changes,\n behaviorChanges,\n summary: { ...summarize(changes), behaviorChanges: behaviorChanges.length },\n };\n}\n\nfunction collectBehaviorChanges(changes: Change[]): BehaviorChange[] {\n const out: BehaviorChange[] = [];\n for (const c of changes) {\n if (c.kind !== 'operation-modified') continue;\n for (const pc of c.paramChanges) {\n if (pc.kind !== 'param-default-changed') continue;\n out.push({\n kind: 'param-default-changed',\n serviceName: c.serviceName,\n operationName: c.operationName,\n paramName: pc.paramName,\n paramLocation: pc.paramLocation ?? 'query',\n oldDefault: pc.oldDefault ?? null,\n newDefault: pc.newDefault ?? null,\n classification: 'breaking',\n });\n }\n }\n return out;\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'enum-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newEnum] of newByName) {\n const oldEnum = oldByName.get(name);\n if (!oldEnum) continue;\n\n const valueChanges = diffEnumValues(oldEnum, newEnum);\n if (valueChanges.length > 0) {\n const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n changes.push({\n kind: 'enum-modified',\n name,\n valueChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n const changes: EnumValueChange[] = [];\n const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n }\n }\n\n for (const [name, newVal] of newByName) {\n const oldVal = oldByName.get(name);\n if (!oldVal) continue;\n\n if (oldVal.value !== newVal.value) {\n changes.push({\n kind: 'value-changed',\n valueName: name,\n classification: 'breaking',\n details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n });\n }\n }\n\n return changes;\n}\n\nfunction summarize(changes: Change[]) {\n let added = 0;\n let removed = 0;\n let modified = 0;\n let breaking = 0;\n let additive = 0;\n\n for (const c of changes) {\n if (c.kind.endsWith('-added')) added++;\n else if (c.kind.endsWith('-removed')) removed++;\n else if (c.kind.endsWith('-modified')) modified++;\n\n if (c.classification === 'breaking') breaking++;\n else additive++;\n }\n\n return { added, removed, modified, breaking, additive };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"diff-IXR1sWSP.mjs","names":["extractDeclarationName","declarationKey","path","path","path"],"sources":["../src/ir/operation-hints.ts","../src/engine/merge-adapters/url-fingerprint.ts","../src/engine/merge-adapters/dotnet.ts","../src/engine/merge-adapters/elixir.ts","../src/engine/merge-adapters/go.ts","../src/engine/merge-adapters/kotlin.ts","../src/engine/merge-adapters/node.ts","../src/engine/merge-adapters/php.ts","../src/engine/merge-adapters/python.ts","../src/engine/merge-adapters/ruby.ts","../src/engine/merge-adapters/rust.ts","../src/engine/merge-adapters/index.ts","../src/engine/merger.ts","../src/engine/json-merge.ts","../src/engine/writer.ts","../src/engine/scoped-services.ts","../src/engine/generate-files.ts","../src/engine/integrate.ts","../src/engine/formatter.ts","../src/engine/manifest.ts","../src/engine/orchestrator.ts","../src/engine/registry.ts","../src/differ/classify.ts","../src/differ/models.ts","../src/differ/operations.ts","../src/differ/services.ts","../src/differ/diff.ts"],"sourcesContent":["import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n return s\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[-\\s.]+/g, '_')\n .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /auth/token\"). */\nexport interface OperationHint {\n /** Override the algorithm-derived method name. */\n name?: string;\n /** Remount this operation to a different service/namespace (PascalCase). */\n mountOn?: string;\n /** Split a union-body operation into N typed wrapper methods. */\n split?: SplitHint[];\n /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n inferFromClient?: string[];\n /**\n * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n * should generate a method that returns the constructed URL (typically as a\n * string) without performing any I/O. Used for OAuth-style redirect endpoints\n * such as /auth/authorize and /accounts/sessions/logout.\n */\n urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n targetVariant: string;\n /** Constant body fields injected by the wrapper. */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime. */\n inferFromClient?: string[];\n /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n exposedParams?: string[];\n /**\n * Subset of exposedParams that should be emitted as optional even when the\n * variant model would otherwise mark them required (or when the variant has\n * no addressable model, as happens for inline oneOf branches).\n */\n optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n /** The original IR operation (preserves description, params, types, etc.). */\n operation: Operation;\n /** The original IR service that owns this operation. */\n service: Service;\n /** Resolved snake_case method name (emitters convert to their convention). */\n methodName: string;\n /** Resolved target service/namespace (PascalCase). */\n mountOn: string;\n /** For split operations: one wrapper per union variant. */\n wrappers?: ResolvedWrapper[];\n /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n defaults: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n inferFromClient: string[];\n /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name. */\n targetVariant: string;\n /** Constant body defaults injected by the wrapper. */\n defaults: Record<string, string | number | boolean>;\n /** Fields read from client config at runtime. */\n inferFromClient: string[];\n /** Body fields exposed as method params. */\n exposedParams: string[];\n /** Optional body fields (not required in the variant). */\n optionalParams: string[];\n /** Response model name (if any). */\n responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n 'accept',\n 'activate',\n 'authorize',\n 'challenge',\n 'check',\n 'complete',\n 'confirm',\n 'deactivate',\n 'disable',\n 'enable',\n 'enroll',\n 'generate',\n 'reactivate',\n 'resend',\n 'revoke',\n 'send',\n 'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n get: 'list',\n post: 'create',\n put: 'update',\n patch: 'update',\n delete: 'delete',\n head: 'get',\n options: 'list',\n trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n if (word.length <= 2) return word;\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n if (\n word.endsWith('ses') ||\n word.endsWith('zes') ||\n word.endsWith('xes') ||\n word.endsWith('ches') ||\n word.endsWith('shes')\n ) {\n return word.slice(0, -2);\n }\n if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n if (word.endsWith('s')) return word.slice(0, -1);\n return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n const segments = op.path.split('/').filter(Boolean);\n\n // Separate static segments from param segments\n const staticSegments: string[] = [];\n let trailingParam = false;\n for (const seg of segments) {\n if (seg.startsWith('{') && seg.endsWith('}')) {\n trailingParam = true;\n } else {\n staticSegments.push(seg);\n trailingParam = false;\n }\n }\n\n if (staticSegments.length === 0) {\n return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n }\n\n const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n // Check if terminal is an action verb\n if (ACTION_VERBS.has(terminal)) {\n // Resource context from preceding segments\n const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n if (resource) {\n return `${terminal}_${resource}`;\n }\n return terminal;\n }\n\n // Determine verb from HTTP method\n let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n // GET with trailing {id} → \"get\" instead of \"list\"\n if (op.httpMethod === 'get' && trailingParam) {\n verb = 'get';\n }\n\n // Build resource name from static segments.\n // When path params separate static segments, include the penultimate static\n // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n // e.g. /projects/{id}/roles → \"project_roles\"\n let resource = toSnake(terminal);\n if (staticSegments.length >= 2) {\n const penultimate = staticSegments[staticSegments.length - 2];\n // Check if a path param appears between the penultimate and terminal segments\n // in the original path by finding both positions and looking for {…} between them.\n const penIdx = segments.lastIndexOf(penultimate);\n const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n if (hasParamBetween) {\n const prefix = toSnake(singularize(penultimate));\n resource = `${prefix}_${resource}`;\n }\n }\n\n // Singularize when:\n // * there's a trailing path param (single-resource read/update/delete), or\n // * the verb itself implies a single-resource operation (e.g. POST → create\n // always creates one item even when posted to a collection endpoint).\n const isSingleResource = trailingParam || verb === 'create';\n const noun = isSingleResource ? singularize(resource) : resource;\n\n // For \"list\" verb, keep plural\n const finalNoun = verb === 'list' ? resource : noun;\n\n return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n spec: ApiSpec,\n hints?: Record<string, OperationHint>,\n mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n const resolved: ResolvedOperation[] = [];\n const hintMap = hints ?? {};\n const mounts = mountRules ?? {};\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const hint = hintMap[key];\n\n // Resolve method name: hint > algorithm\n const methodName = hint?.name ?? deriveMethodName(op, service);\n\n // Resolve mount target: per-op hint > service mount rule > original service\n const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n // Build wrappers for split operations\n let wrappers: ResolvedWrapper[] | undefined;\n if (hint?.split) {\n wrappers = hint.split.map((sh) => ({\n name: sh.name,\n targetVariant: sh.targetVariant,\n defaults: sh.defaults ?? {},\n inferFromClient: sh.inferFromClient ?? [],\n exposedParams: sh.exposedParams ?? [],\n optionalParams: sh.optionalParams ?? [],\n responseModelName: resolveResponseModelName(op),\n }));\n }\n\n resolved.push({\n operation: op,\n service,\n methodName,\n mountOn,\n wrappers,\n defaults: hint?.defaults ?? {},\n inferFromClient: hint?.inferFromClient ?? [],\n urlBuilder: hint?.urlBuilder ?? false,\n });\n }\n }\n\n return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n if (op.httpMethod === 'delete') return null;\n const ref = op.response;\n if (ref.kind === 'model') return ref.name;\n if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n return null;\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n const stringTypes = new Set(config.stringNodeTypes);\n const contentTypes = new Set(config.contentNodeTypes);\n const interpolationTypes = new Set(config.interpolationNodeTypes);\n const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n // Iterative DFS through the method's AST subtree\n const stack: Parser.SyntaxNode[] = [memberNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (stringTypes.has(node.type)) {\n const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // For format functions (Go's Sprintf, Rust's format!): check if this call\n // matches and extract the first string argument.\n if (formatFns && isFormatCall(node, formatFns)) {\n const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // Push children in reverse order so leftmost child is processed first\n for (let i = node.childCount - 1; i >= 0; i--) {\n const child = node.child(i);\n if (child) stack.push(child);\n }\n }\n\n return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n stringNode: Parser.SyntaxNode,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n // Leaf string node (no children besides quotes) — strip quotes\n if (stringNode.namedChildCount === 0) {\n return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n }\n\n // Composite string (has content fragments + interpolation children)\n let result = '';\n for (let i = 0; i < stringNode.childCount; i++) {\n const child = stringNode.child(i)!;\n if (contentTypes.has(child.type)) {\n result += child.text;\n } else if (interpolationTypes.has(child.type)) {\n result += '{}';\n }\n // Skip quote delimiters, interpolation markers, etc.\n }\n\n return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n if (node.type === 'macro_invocation') {\n const macroName = node.childForFieldName('macro')?.text;\n return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n }\n\n if (node.type !== 'call_expression') return false;\n const fnNode = node.childForFieldName('function');\n if (!fnNode) return false;\n\n // Direct call: Sprintf(...) or format!(...)\n if (formatFns.has(fnNode.text)) return true;\n\n // Member call: fmt.Sprintf(...)\n if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n if (prop && formatFns.has(prop.text)) return true;\n }\n return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n callNode: Parser.SyntaxNode,\n stringTypes: Set<string>,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n const args = callNode.childForFieldName('arguments');\n if (!args) return undefined;\n\n for (let i = 0; i < args.childCount; i++) {\n const arg = args.child(i)!;\n if (stringTypes.has(arg.type)) {\n return resolveFingerprint(arg, contentTypes, interpolationTypes);\n }\n }\n return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n contentNodeTypes: ['string_content', 'string_literal_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n 'class_declaration',\n 'struct_declaration',\n 'interface_declaration',\n 'enum_declaration',\n 'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (DECLARATION_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n const nameNode =\n node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode ? `__namespace:${nameNode.text}` : null;\n }\n return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n children: Parser.SyntaxNode[],\n source: string,\n statements: MergeStatement[],\n imports: MergeImport[],\n importAnchors: string[],\n importInsertionAnchor: { value?: string },\n): void {\n for (const child of children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'using_directive') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n if (child.type === 'file_scoped_namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // File-scoped namespace: subsequent declarations are siblings at root\n continue;\n }\n\n if (child.type === 'namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // Block namespace: recurse into declaration_list\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n language: 'dotnet',\n grammarModule: 'tree-sitter-c-sharp',\n testFilePatterns: [/Tests?\\.cs$/],\n urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n const importInsertionAnchor: { value?: string } = {};\n\n collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n return {\n imports,\n importAnchors,\n importInsertionAnchor: importInsertionAnchor.value,\n statements,\n };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n\n function processChildren(children: Parser.SyntaxNode[]): void {\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Recurse into namespaces\n if (child.type === 'namespace_declaration') {\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) processChildren(body.children);\n continue;\n }\n\n const name = extractDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = collectPrecedingXmlDocComments(children, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n // For methods, the second identifier is the name (first is return type)\n const identifiers = member.children.filter((c) => c.type === 'identifier');\n const memberName =\n member.type === 'method_declaration'\n ? identifiers.length >= 2\n ? identifiers[1]!.text\n : identifiers[0]?.text\n : identifiers[0]?.text;\n if (!memberName) continue;\n const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n }\n\n processChildren(tree.rootNode.children);\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['quoted_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n if (!isDefmodule(node)) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n const alias = args.children.find((c) => c.type === 'alias');\n return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'unary_operator') return null;\n const call = node.children.find((c) => c.type === 'call');\n if (!call) return null;\n const id = call.children.find((c) => c.type === 'identifier');\n if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'call') return null;\n const id = node.children[0];\n if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n // The function name is either a simple identifier or a call (for functions with params)\n for (const arg of args.namedChildren) {\n if (arg.type === 'identifier') return arg.text;\n if (arg.type === 'call') {\n const nameNode = arg.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n }\n return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const id = node.children[0];\n return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n language: 'elixir',\n grammarModule: 'tree-sitter-elixir',\n testFilePatterns: [/_test\\.exs$/],\n urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n // Top-level alias/import/require/use (rare but possible outside modules)\n if (isImportLike(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const moduleName = getModuleName(child);\n statements.push({\n key: moduleName,\n kind: moduleName ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const moduleName = getModuleName(child);\n if (!moduleName) continue;\n\n // Look for @moduledoc inside the do_block\n let docstring: DocstringInfo | null = null;\n const doBlock = getDoBlock(child);\n const members = new Map<string, MemberDocstrings>();\n\n if (doBlock) {\n const bodyChildren = doBlock.children;\n\n // Find @moduledoc\n for (const bodyChild of bodyChildren) {\n if (isDocAttribute(bodyChild) === 'moduledoc') {\n docstring = {\n text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n startIndex: bodyChild.startIndex,\n endIndex: bodyChild.endIndex,\n };\n break;\n }\n }\n\n // Find @doc + def pairs for member docstrings\n for (let j = 0; j < bodyChildren.length; j++) {\n const bodyChild = bodyChildren[j];\n const defName = getDefName(bodyChild);\n if (!defName) continue;\n\n // Look for preceding @doc attribute\n let memberDoc: DocstringInfo | null = null;\n for (let k = j - 1; k >= 0; k--) {\n const prev = bodyChildren[k];\n if (isDocAttribute(prev) === 'doc') {\n memberDoc = {\n text: source.slice(prev.startIndex, prev.endIndex),\n startIndex: prev.startIndex,\n endIndex: prev.endIndex,\n };\n break;\n }\n if (prev.type === 'comment') continue;\n break;\n }\n\n members.set(defName, {\n docstring: memberDoc,\n declStartIndex: bodyChild.startIndex,\n declColumn: bodyChild.startPosition.column,\n urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(moduleName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['interpreted_string_literal'],\n contentNodeTypes: ['interpreted_string_literal_content'],\n interpolationNodeTypes: [],\n formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n const receiver = node.childForFieldName('receiver');\n if (!receiver) return null;\n return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'package_clause': {\n const pkg = lastIdentifier(node.text);\n return pkg ? `__package:${pkg}` : '__package:';\n }\n case 'type_declaration': {\n const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n const nameNode = spec?.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'function_declaration': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'method_declaration': {\n const name = node.childForFieldName('name')?.text ?? null;\n const receiver = receiverKey(node);\n return name && receiver ? `method:${receiver}.${name}` : name;\n }\n case 'const_declaration':\n case 'var_declaration': {\n return node.text.split(/\\s+/).slice(0, 3).join(' ');\n }\n default:\n return null;\n }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n const entries: MergeImport[] = [];\n\n const collect = (spec: Parser.SyntaxNode): void => {\n const path = spec.childForFieldName('path')?.text ?? spec.text;\n const name = spec.childForFieldName('name')?.text ?? '';\n const text = source.slice(spec.startIndex, spec.endIndex);\n entries.push({\n key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n text,\n });\n };\n\n for (const child of node.namedChildren) {\n if (child.type === 'import_spec') {\n collect(child);\n continue;\n }\n if (child.type === 'import_spec_list') {\n for (const spec of child.namedChildren) {\n if (spec.type === 'import_spec') collect(spec);\n }\n }\n }\n\n return entries;\n}\n\nfunction collectPrecedingGoComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('//')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n language: 'go',\n grammarModule: 'tree-sitter-go',\n testFilePatterns: [/_test\\.go$/],\n urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'package_clause') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'import_declaration') {\n imports.push(...importEntries(child, source));\n importAnchors.push(source.slice(child.startIndex, child.endIndex));\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n if (imports.length === 0) return [];\n if (imports.length === 1) return [`import ${imports[0]!.text}`];\n return [`import (\\n${imports.map((entry) => ` ${entry.text}`).join('\\n')}\\n)`];\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key || key.startsWith('__package:')) continue;\n\n const docstring = collectPrecedingGoComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n MergeMember,\n DeepMergeSymbol,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_declaration') {\n // Handles class, data class, enum class, etc.\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'function_declaration') {\n const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'object_declaration') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'type_alias') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'property_declaration') {\n const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n if (nameNode) {\n const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n return id?.text ?? null;\n }\n }\n return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === 'line_comment') continue;\n return null;\n }\n return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n const children = classBody.namedChildren;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n let memberName: string | null = null;\n\n if (child.type === 'property_declaration') {\n const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'function_declaration') {\n memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'companion_object') {\n memberName = 'companion';\n }\n\n if (!memberName) continue;\n\n // Fold trailing getter/setter into the property's text span\n let endIdx = child.endIndex;\n if (child.type === 'property_declaration') {\n while (i + 1 < children.length) {\n const next = children[i + 1];\n if (next.type === 'getter' || next.type === 'setter') {\n endIdx = next.endIndex;\n i++;\n } else {\n break;\n }\n }\n }\n\n // Include preceding KDoc comment in the text span so deep merge\n // inserts the member with its documentation intact.\n let startIdx = child.startIndex;\n for (let k = i - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) startIdx = prev.startIndex;\n break;\n }\n if (prev.type === 'line_comment') continue;\n break;\n }\n\n members.push({ key: memberName, text: source.slice(startIdx, endIdx), startIndex: startIdx, endIndex: endIdx });\n }\n\n return members;\n}\n\n/**\n * KDoc signature that identifies a generator-emitted service accessor inside\n * a Kotlin client class. The Kotlin client emitter writes every accessor with this\n * exact doc preamble — when the existing file carries a member with this doc\n * but the regenerated content omits it, the member is stale (its mount target\n * was remapped or removed) and gets pruned.\n */\nconst KOTLIN_MANAGED_ACCESSOR_DOC =\n /\\/\\*\\*[\\s\\S]*?Lazily-constructed \\[[^\\]]+\\] accessor for this \\[[^\\]]+\\] client\\.[\\s\\S]*?\\*\\//;\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n language: 'kotlin',\n grammarModule: 'tree-sitter-kotlin',\n testFilePatterns: [/Test\\.kt$/],\n urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n if (child.type === 'import_list') {\n const fullText = source.slice(child.startIndex, child.endIndex);\n importAnchors.push(fullText);\n for (const imp of child.namedChildren) {\n if (imp.type === 'import_header') {\n const text = source.slice(imp.startIndex, imp.endIndex).trim();\n // Key on the full import path\n const idNode = imp.children.find((c) => c.type === 'identifier');\n const key = idNode?.text ?? text;\n imports.push({ key, text });\n }\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n isManagedMember(member) {\n return KOTLIN_MANAGED_ACCESSOR_DOC.test(member.text);\n },\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // Skip if new members reference instance properties that don't exist in the target\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) return true;\n }\n return false;\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'class_declaration') continue;\n const nameNode = child.children.find((c) => c.type === 'type_identifier');\n if (!nameNode) continue;\n const body = child.children.find((c) => c.type === 'class_body');\n if (!body) continue;\n\n const members = extractKotlinClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractDeclarationName(child);\n if (!name) continue;\n\n const docstring = findPrecedingKdoc(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings for classes\n if (child.type === 'class_declaration') {\n const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n const memberName = extractDeclarationName(member);\n if (!memberName) continue;\n const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DeepMergeSymbol,\n MergeMember,\n DocstringInfo,\n SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode.text;\n\n if (node.type === 'lexical_declaration') {\n const declarator = node.firstNamedChild;\n if (declarator?.type === 'variable_declarator') {\n const name = declarator.childForFieldName('name');\n if (name) return name.text;\n }\n }\n\n return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n if (node.type === 'export_statement') {\n const decl = node.childForFieldName('declaration');\n if (decl) {\n return { key: extractDeclName(decl), kind: 'declaration' };\n }\n\n const source = node.childForFieldName('source');\n if (source) {\n return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n }\n\n return { key: null, kind: 'other' };\n }\n return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of classBody.namedChildren) {\n if (child.type === 'method_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode && nameNode.text !== 'constructor') {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'public_field_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n // tree-sitter may exclude the trailing semicolon from\n // public_field_definition nodes — include it if present\n let endIdx = child.endIndex;\n if (source[endIdx] === ';') {\n endIdx += 1;\n }\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n }\n }\n }\n return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'property_signature' || child.type === 'method_signature') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n }\n return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'enum_assignment') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'property_identifier') {\n members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n // tree-sitter extras (comments) may report the parent node's type\n // instead of 'comment' — check grammarType as fallback\n return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (isCommentNode(prev)) {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string', 'template_string'],\n contentNodeTypes: ['string_fragment'],\n interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n body: Parser.SyntaxNode,\n source: string,\n memberTypes: Set<string>,\n): Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n const result = new Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n >();\n const allChildren = body.children;\n for (let i = 0; i < allChildren.length; i++) {\n const child = allChildren[i];\n if (!memberTypes.has(child.type)) continue;\n let memberName: string | null = null;\n if (child.type === 'property_identifier') {\n memberName = child.text;\n } else {\n const nameNode = child.childForFieldName('name');\n if (nameNode) memberName = nameNode.text;\n }\n if (!memberName || memberName === 'constructor') continue;\n const docstring = findPrecedingDocstring(allChildren, i, source);\n const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n result.set(memberName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n urlFingerprint: fp,\n });\n }\n return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n language: 'node',\n grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n normalizeReexport: normalizeJsExtension,\n testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // If new members reference instance properties (this.X) that don't exist\n // in the target class, the merged code would be broken.\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) {\n return true;\n }\n }\n return false;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n // Key on module path so `import { X }` and `import type { X }` from\n // the same module are treated as duplicates\n const sourceNode = child.childForFieldName('source');\n const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n imports.push({ key: modulePath, text });\n importAnchors.push(text);\n continue;\n }\n\n const { key, kind } = extractNodeKey(child);\n statements.push({\n key,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n const symbolName = nameNode.text;\n\n if (decl.type === 'class_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'interface_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractInterfaceMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'enum_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractEnumMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n\n // Find preceding JSDoc for this top-level symbol\n const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n // Extract member-level docstrings\n let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n const body = decl.childForFieldName('body');\n if (body) {\n if (decl.type === 'class_declaration') {\n members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n } else if (decl.type === 'interface_declaration') {\n members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n } else if (decl.type === 'enum_declaration') {\n members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n }\n }\n\n result.set(nameNode.text, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['encapsed_string', 'string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'class_declaration':\n case 'interface_declaration':\n case 'trait_declaration':\n case 'enum_declaration':\n case 'function_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'namespace_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n }\n default:\n return null;\n }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n language: 'php',\n grammarModule: 'tree-sitter-php',\n testFilePatterns: [/Test\\.php$/],\n urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n resolveGrammar: (mod) => {\n // ESM import wraps in { default: { php, php_only } }\n const m = (mod as Record<string, unknown>)?.default ?? mod;\n if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n return (m as { php: unknown }).php;\n return m;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'namespace_definition') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'namespace_use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPhpDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPhpDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = findPhpDocstring(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n const body = child.childForFieldName('body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n const memberDoc = findPhpDocstring(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_definition' || node.type === 'function_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n\n // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n if (node.type === 'expression_statement') {\n const firstChild = node.firstNamedChild;\n if (firstChild?.type === 'assignment') {\n const left = firstChild.childForFieldName('left');\n if (left?.type === 'identifier' && left.text === '__all__') {\n return '__all__';\n }\n }\n }\n\n return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n // Python docstrings are the first expression_statement in a body block\n // where the expression is a string literal\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'expression_statement') {\n const expr = child.firstNamedChild;\n if (expr?.type === 'string') {\n const text = source.slice(child.startIndex, child.endIndex);\n return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n }\n }\n // Only the FIRST statement can be a docstring\n break;\n }\n return null;\n}\n\nfunction collectPrecedingPythonComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n language: 'python',\n grammarModule: 'tree-sitter-python',\n testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPythonDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPythonDeclarationName(child);\n if (!name) continue;\n\n // Python: class/function docstrings are inside the body, OR use # comments before\n let docstring: DocstringInfo | null = null;\n const body = child.childForFieldName('body');\n if (body) {\n docstring = extractPythonDocstring(body, source);\n }\n // Fallback: check for # comments before the declaration\n if (!docstring) {\n docstring = collectPrecedingPythonComments(rootChildren, i, source);\n }\n\n const members = new Map<string, MemberDocstrings>();\n\n // Extract method docstrings for classes\n if (child.type === 'class_definition' && body) {\n for (const member of body.namedChildren) {\n if (member.type !== 'function_definition') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null = null;\n const memberBody = member.childForFieldName('body');\n if (memberBody) {\n memberDoc = extractPythonDocstring(memberBody, source);\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const method = node.childForFieldName('method');\n if (!method) return false;\n return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'class' && node.type !== 'module') return null;\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n const nodeType = (prev as any).grammarType ?? prev.type;\n if (nodeType === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('#')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n language: 'ruby',\n grammarModule: 'tree-sitter-ruby',\n testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n const declarationName = extractRubyDeclarationName(child);\n if (isRequireCall(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractRubyDeclarationName(child);\n if (!name) continue;\n\n const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Ruby class/module bodies: comments may appear in class children\n // (before body_statement) or in body_statement children (between methods)\n if (child.type === 'class' || child.type === 'module') {\n const allClassChildren = child.children;\n const body = child.childForFieldName('body');\n\n // Check for comment before body_statement in class children\n // (docstring for the first method)\n let firstMethodDocFromClass: DocstringInfo | null = null;\n for (let j = 0; j < allClassChildren.length; j++) {\n if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n break;\n }\n }\n\n if (body) {\n const bodyChildren = body.children;\n let firstMethodHandled = false;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null;\n if (!firstMethodHandled && firstMethodDocFromClass) {\n memberDoc = firstMethodDocFromClass;\n firstMethodHandled = true;\n } else {\n memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n firstMethodHandled = true;\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'struct_item':\n case 'enum_item':\n case 'function_item':\n case 'trait_item':\n case 'type_item':\n case 'const_item': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'impl_item': {\n const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n const traitName = node.childForFieldName('trait')?.text;\n return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n }\n default:\n return null;\n }\n}\n\nfunction collectPrecedingRustDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'line_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n language: 'rust',\n grammarModule: 'tree-sitter-rust',\n testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key) continue;\n\n const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n ['dotnet', dotnetMergeAdapter],\n ['elixir', elixirMergeAdapter],\n ['go', goMergeAdapter],\n ['kotlin', kotlinMergeAdapter],\n ['node', nodeMergeAdapter],\n ['php', phpMergeAdapter],\n ['python', pythonMergeAdapter],\n ['ruby', rubyMergeAdapter],\n ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n return adapters.get(language);\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc. This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n // Check if the existing docstring contains @deprecated anywhere\n if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n // If generated doc already has @deprecated, no need to merge\n if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n // Extract the @deprecated content from the existing doc.\n // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n const deprecatedParts: string[] = [];\n for (const line of existingDoc.split('\\n')) {\n if (/@deprecated\\b/.test(line)) {\n // Normalize to JSDoc member format: ` * @deprecated ...`\n const match = line.match(/@deprecated\\b.*/);\n if (match) {\n // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n deprecatedParts.push(` * ${cleaned}`);\n }\n }\n }\n if (deprecatedParts.length === 0) return generatedDoc;\n\n // Insert @deprecated lines before the closing */ of the generated doc\n const closingIdx = generatedDoc.lastIndexOf('*/');\n if (closingIdx === -1) return generatedDoc;\n const before = generatedDoc.slice(0, closingIdx);\n const after = generatedDoc.slice(closingIdx);\n return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n startIndex: number;\n endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n const regions: IgnoredRegion[] = [];\n const startTag = '@oagen-ignore-start';\n const endTag = '@oagen-ignore-end';\n let searchFrom = 0;\n\n while (true) {\n const startIdx = source.indexOf(startTag, searchFrom);\n if (startIdx === -1) break;\n const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n if (endIdx === -1) break; // Unclosed — silently ignore\n regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n searchFrom = endIdx + endTag.length;\n }\n\n return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n if (regions.length === 0) return new Set();\n const ignored = new Set<string>();\n for (const [name, info] of docstrings) {\n if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n ignored.add(name);\n }\n }\n return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n if (!Number.isFinite(value)) return 0;\n if (value < 0) return 0;\n if (value > contentLength) return contentLength;\n return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n const idx = clampIndex(declStartIndex, content.length);\n const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n content: string,\n docText: string,\n declStartIndex: number,\n fallbackStart: number,\n fallbackEnd: number,\n): { start: number; end: number } {\n const safeDecl = clampIndex(declStartIndex, content.length);\n const safeFallbackStart = clampIndex(fallbackStart, content.length);\n const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n const found = content.lastIndexOf(docText, safeDecl);\n if (found !== -1) {\n return { start: found, end: found + docText.length };\n }\n return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n const cached = parserCache.get(language);\n if (cached) return cached;\n\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(\n `No tree-sitter grammar configured for language \"${language}\". ` +\n `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n );\n }\n\n const mod = await import(adapter.grammarModule);\n const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n const grammar = (exported as { default?: unknown }).default ?? exported;\n const parser = new Parser();\n parser.setLanguage(grammar);\n parserCache.set(language, parser);\n return parser;\n}\n\ninterface ParsedSymbols {\n names: Set<string>;\n /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n if (typeof source !== 'string') {\n throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n }\n const tree = safeParse(parser, source);\n const names = new Set<string>();\n const unnamedTexts = new Set<string>();\n const parsed = adapter.parseStatements(tree, source);\n\n for (const imp of parsed.imports) {\n names.add(imp.key);\n }\n for (const statement of parsed.statements) {\n if (statement.key) {\n names.add(statement.key);\n } else {\n unnamedTexts.add(statement.text.trim());\n }\n }\n\n return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n const tree = safeParse(parser, source);\n return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter. `bodyEndLine` is 0-based. For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n source: string,\n language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n const parser = await getParser(language);\n const tree = safeParse(parser, source);\n const map = new Map<string, { bodyEndLine: number }>();\n\n function processClassNode(node: Parser.SyntaxNode): void {\n const nameNode =\n node.childForFieldName('name') ??\n node.children.find((c) => c.type === 'type_identifier' || c.type === 'identifier');\n if (!nameNode) return;\n const name = nameNode.text;\n\n const body =\n node.childForFieldName('body') ?? node.children.find((c) => c.type === 'class_body' || c.type === 'body');\n const endRow = body ? body.endPosition.row : node.endPosition.row;\n const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n if (lastChar === '}') {\n map.set(name, { bodyEndLine: endRow });\n } else {\n map.set(name, { bodyEndLine: endRow + 1 });\n }\n }\n\n // Walk the tree recursively. Ruby (and Python) often nest target classes\n // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n // root children would miss them.\n function walk(node: Parser.SyntaxNode): void {\n if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n processClassNode(node);\n }\n if (node.type === 'decorated_definition') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_definition') processClassNode(inner);\n }\n }\n if (node.type === 'export_statement') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_declaration') processClassNode(inner);\n }\n }\n for (const child of node.namedChildren) walk(child);\n }\n for (const child of tree.rootNode.children) {\n walk(child);\n }\n\n return map;\n}\n\nexport interface MergeResult {\n content: string;\n added: number;\n preserved: number;\n changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n existingContent: string,\n generatedContent: string,\n language: string,\n header: string,\n): Promise<MergeResult> {\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n\n // Parse existing file once — extract both symbols and statements from the same AST pass\n const existingStatements = await extractStatements(existingContent, language);\n const generatedStatements = await extractStatements(generatedContent, language);\n\n const existingKeys = new Set<string>();\n const existingUnnamedTexts = new Set<string>();\n const existingImportKeys = new Set<string>();\n const existingReexports = new Set<string>();\n let lastImportEndIndex = -1;\n\n // Collect import keys AND imported identifiers (to prevent adding declarations\n // that clash with already-imported names)\n const existingImportedNames = new Set<string>();\n for (const imp of existingStatements.imports) {\n existingImportKeys.add(imp.key);\n // Extract identifiers from import text: import { Foo, Bar } from '...'\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const name of braceMatch[1].split(',')) {\n const trimmed = name.replace(/\\btype\\b/, '').trim();\n if (trimmed) existingImportedNames.add(trimmed);\n }\n }\n }\n for (const anchor of existingStatements.importAnchors) {\n const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n const stmtLines = anchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n const linesBefore =\n existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n 1;\n const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n\n // Track all names exported by existing statements (both direct exports and\n // re-export aliases like `export { X as Y }`). Used to prevent the merger\n // from appending a re-export that introduces a duplicate exported name.\n const existingExportedNames = new Set<string>();\n\n for (const stmt of existingStatements.statements) {\n if (stmt.kind === 'reexport') {\n existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n // Collect aliased export names from re-exports\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const part of braceMatch[1].split(',')) {\n const segments = part.trim().split(/\\s+as\\s+/);\n const exportedName = (segments[1] ?? segments[0]).trim();\n if (exportedName) existingExportedNames.add(exportedName);\n }\n }\n }\n if (stmt.key) {\n existingKeys.add(stmt.key);\n existingExportedNames.add(stmt.key);\n } else {\n existingUnnamedTexts.add(stmt.text.trim());\n }\n }\n\n const headerLine = header.trim();\n\n const newImports: MergeImport[] = [];\n const toAppend: string[] = [];\n let preserved = 0;\n\n for (const imp of generatedStatements.imports) {\n if (imp.text.trim() === headerLine) continue;\n if (existingImportKeys.has(imp.key)) {\n // The existing file already imports from this module path.\n // Check if the generated import adds identifiers not present in\n // the existing import — if so, create a supplemental import with\n // only the new identifiers. The supplemental participates in the\n // usage-based filter (below) so unused identifiers are dropped.\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n if (newNames.length > 0) {\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n newImports.push({\n key: imp.key + '#supplemental',\n text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n }\n }\n }\n preserved++;\n continue;\n }\n // Strip out identifiers that are already imported from another path.\n // This prevents duplicates when the generated file uses a specific path\n // (e.g., '../interfaces/organization.interface') while the existing file\n // imports the same names from a barrel (e.g., '../interfaces').\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n // Check against both existing imports AND existing top-level declarations\n const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n if (names.length > 0 && names.every(isAlreadyDefined)) {\n preserved++;\n continue;\n }\n // If only SOME identifiers are already defined, strip them out and keep only new ones\n if (names.some(isAlreadyDefined)) {\n const newNames = names.filter((n) => !isAlreadyDefined(n));\n if (newNames.length === 0) {\n preserved++;\n continue;\n }\n // Rebuild the import with only new identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n newImports.push({ key: imp.key, text: newText });\n continue;\n }\n }\n }\n newImports.push(imp);\n }\n\n for (const stmt of generatedStatements.statements) {\n // Skip the header comment\n if (stmt.text.trim() === headerLine) continue;\n\n // Skip re-export statements that duplicate existing re-exports\n // (e.g., generated uses .js extension but existing doesn't).\n // Allow genuinely new re-exports through.\n if (stmt.kind === 'reexport') {\n const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n preserved++;\n continue;\n }\n // Also skip re-exports whose aliased names are already defined as\n // top-level exports in the existing file (e.g., generated file has\n // `export { X as deserializeFoo } from '...'` but existing file\n // already has `export const deserializeFoo = ...`).\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const exportedNames = braceMatch[1]\n .split(',')\n .map((n) => {\n const parts = n.trim().split(/\\s+as\\s+/);\n return (parts[1] ?? parts[0]).trim();\n })\n .filter(Boolean);\n if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n preserved++;\n continue;\n }\n }\n }\n\n if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n preserved++;\n continue;\n }\n\n if (!stmt.key) {\n if (existingUnnamedTexts.has(stmt.text.trim())) {\n preserved++;\n continue;\n }\n }\n\n toAppend.push(stmt.text);\n }\n\n if (newImports.length === 0 && toAppend.length === 0) {\n // No top-level changes — check for deep merge before returning\n if (!adapter.extractMembers) {\n // Still need to check docstring refresh below\n }\n }\n\n let result = existingContent;\n\n // Append new top-level symbols first (so deep merge can see them)\n if (toAppend.length > 0) {\n result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n }\n\n // Deep merge pass: add new members to existing symbols\n // Runs after import/symbol merge so line numbers are based on the updated content\n let deepAdded = 0;\n let deepPruned = 0;\n const insertions: { line: number; text: string }[] = [];\n if (adapter.extractMembers) {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultSymbols = adapter.extractMembers(resultTree, result);\n const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n const existingTree = safeParse(parser, existingContent);\n const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n const deepIgnoredRegions = findIgnoredRegions(existingContent);\n const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n // Pass 1: prune stale \"managed\" members (existing members the adapter\n // recognizes as generator-owned but that no longer appear in the\n // regenerated content — e.g. accessors whose mount target was remapped).\n // Done as byte-range deletes before line-based insertions so insertion\n // line numbers stay valid for the post-prune result.\n if (adapter.isManagedMember) {\n const pruneEdits: { start: number; end: number }[] = [];\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue;\n const genMemberKeys = new Set(genSymbol.members.map((m) => m.key));\n for (const existMember of existSymbol.members) {\n if (genMemberKeys.has(existMember.key)) continue;\n if (existMember.startIndex === undefined || existMember.endIndex === undefined) continue;\n if (!adapter.isManagedMember(existMember)) continue;\n pruneEdits.push({ start: existMember.startIndex, end: existMember.endIndex });\n }\n }\n if (pruneEdits.length > 0) {\n pruneEdits.sort((a, b) => b.start - a.start);\n for (const edit of pruneEdits) {\n let end = edit.end;\n while (end < result.length && (result[end] === ' ' || result[end] === '\\t')) end++;\n if (result[end] === '\\n') end++;\n result = result.slice(0, edit.start) + result.slice(end);\n }\n deepPruned = pruneEdits.length;\n // Re-extract since byte offsets and line numbers shifted.\n const reTree = safeParse(parser, result);\n resultSymbols.clear();\n for (const [k, v] of adapter.extractMembers(reTree, result)) resultSymbols.set(k, v);\n }\n }\n\n // Pass 2: append new members the regenerated content adds.\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue; // New symbol — handled by top-level append\n\n const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n if (newMembers.length > 0) {\n // Let the adapter decide whether to skip deep merge (e.g., when new members\n // reference dependencies the existing symbol doesn't provide)\n if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n continue;\n }\n\n const indent = existSymbol.memberIndent ?? ' ';\n const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n // Leading blank line separates inserted members from existing ones.\n insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n deepAdded += newMembers.length;\n }\n }\n\n if (insertions.length > 0) {\n // Apply bottom-up to avoid offset shifting\n insertions.sort((a, b) => b.line - a.line);\n const resultLines = result.split('\\n');\n for (const ins of insertions) {\n resultLines.splice(ins.line, 0, ins.text);\n }\n result = resultLines.join('\\n');\n }\n }\n\n // Insert new imports only when new symbols or members were actually added.\n // This prevents orphaned imports for generated code that wasn't merged in.\n // Additionally, filter imports to only include identifiers actually used in the\n // appended/inserted code — prevents orphaned imports for generated code that\n // referenced types used in other (non-appended) generated functions.\n if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n // Build text of all new code that was actually added (appended + deep-merged members)\n const addedParts: string[] = [...toAppend];\n if (insertions) {\n for (const ins of insertions) {\n addedParts.push(ins.text);\n }\n }\n const addedCodeText = addedParts.join('\\n');\n\n // Filter imports to only identifiers that appear in the added code.\n // Strip individual unused identifiers from each import rather than\n // keeping/dropping the entire import — prevents orphaned imports when\n // a generated import line contains both used and unused identifiers\n // (e.g., `import { deserializeFoo, serializeFoo }` where only\n // serializeFoo is used in the appended code).\n const filteredImports: MergeImport[] = [];\n for (const imp of newImports) {\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (!braceMatch) {\n // Non-destructured import (e.g., default import) — keep as-is\n filteredImports.push(imp);\n continue;\n }\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const usedNames = names.filter((name) => addedCodeText.includes(name));\n if (usedNames.length === 0) continue; // Drop entirely\n if (usedNames.length === names.length) {\n // All identifiers used — keep original import\n filteredImports.push(imp);\n } else {\n // Rebuild import with only used identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n filteredImports.push({\n key: imp.key,\n text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n } else {\n filteredImports.push(imp);\n }\n }\n }\n\n if (filteredImports.length > 0) {\n const renderedImports = adapter.renderImports\n ? adapter.renderImports(filteredImports)\n : filteredImports.map((entry) => entry.text);\n const lines = result.split('\\n');\n const insertIdx = lastImportEndIndex + 1;\n lines.splice(insertIdx, 0, ...renderedImports);\n result = lines.join('\\n');\n }\n }\n\n // Docstring refresh pass: update existing docstrings to match generated content\n let docstringUpdates = 0;\n {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultDocs = adapter.extractDocstrings(resultTree, result);\n const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n const docIgnoredRegions = findIgnoredRegions(result);\n const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n const edits: { start: number; end: number; newText: string }[] = [];\n\n for (const [symbolName, genInfo] of generatedDocs) {\n const existInfo = resultDocs.get(symbolName);\n if (!existInfo) continue;\n if (docIgnoredSymbols.has(symbolName)) continue;\n\n // Skip header comments being treated as docstrings\n const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n // Top-level docstring\n if (genDoc) {\n if (existInfo.docstring) {\n const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n const range = resolveDocRange(\n result,\n existInfo.docstring.text,\n existInfo.declStartIndex,\n existInfo.docstring.startIndex,\n existInfo.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n const indent = ' '.repeat(existInfo.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genDoc.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — first pass: match by name\n const matchedExistMembers = new Set<string>();\n for (const [memberName, genMember] of genInfo.members) {\n const existMember = existInfo.members.get(memberName);\n if (!existMember) continue;\n matchedExistMembers.add(memberName);\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — second pass: URL fingerprint fallback\n // Match generated members to existing members by URL pattern when\n // name-based matching fails (e.g., generated \"find\" vs existing \"getWidget\"\n // both call this.client.get('/widgets/${id}')).\n //\n // Safety: only attempt fingerprint matching when there is exactly ONE\n // unmatched generated member and ONE unmatched existing member for a\n // given fingerprint. When multiple members share the same URL path\n // (e.g., POST and GET on /authorization/roles), fingerprint matching\n // is ambiguous and would swap docstrings between methods.\n const unmatchedGenByFp = new Map<\n string,\n { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [genName, genMember] of genInfo.members) {\n if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n if (!genMember.docstring || !genMember.urlFingerprint) continue;\n // Skip if this generated member was already name-matched\n if (existInfo.members.has(genName)) continue;\n const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n bucket.push({ name: genName, member: genMember });\n unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n }\n const unmatchedExistByFp = new Map<\n string,\n { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [existName, existMember] of existInfo.members) {\n if (matchedExistMembers.has(existName)) continue;\n if (!existMember.urlFingerprint) continue;\n const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n bucket.push({ name: existName, member: existMember });\n unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n }\n for (const [fp, genBucket] of unmatchedGenByFp) {\n if (genBucket.length !== 1) continue; // ambiguous — skip\n const existBucket = unmatchedExistByFp.get(fp);\n if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n const genMember = genBucket[0].member;\n const existEntry = existBucket[0];\n const existMember = existEntry.member;\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (isPreserved) continue;\n if (existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n matchedExistMembers.add(existEntry.name);\n }\n }\n\n if (edits.length > 0) {\n edits.sort((a, b) => b.start - a.start);\n for (const edit of edits) {\n result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n }\n }\n }\n\n const importsActuallyAdded =\n toAppend.length > 0 || deepAdded > 0\n ? adapter.renderImports\n ? adapter.renderImports(newImports).length\n : newImports.length\n : 0;\n const topLevelAdded = importsActuallyAdded + toAppend.length;\n const totalAdded = topLevelAdded + deepAdded;\n\n if (totalAdded === 0 && docstringUpdates === 0 && deepPruned === 0) {\n return { content: existingContent, added: 0, preserved, changed: false };\n }\n\n return {\n content: result,\n added: totalAdded,\n preserved,\n changed: true,\n };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n if (\n typeof existing === 'object' &&\n existing !== null &&\n !Array.isArray(existing) &&\n typeof generated === 'object' &&\n generated !== null &&\n !Array.isArray(generated)\n ) {\n const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n if (key in merged) {\n merged[key] = deepMergeJson(merged[key], value);\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n // Arrays and primitives: generated wins\n return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines, extractStatements } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n * tree-sitter grammar for AST-level merging. */\n language?: string;\n /** The auto-generated file header string. */\n header?: string;\n}\n\nexport interface WriteResult {\n written: string[];\n merged: string[];\n skipped: string[];\n identical: string[];\n ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n files: GeneratedFile[],\n outputDir: string,\n options?: WriteOptions,\n): Promise<WriteResult> {\n const result: WriteResult = {\n written: [],\n merged: [],\n skipped: [],\n identical: [],\n ignored: [],\n };\n const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n const language = options?.language;\n const header = options?.header ?? '';\n\n for (const file of sorted) {\n const fullPath = path.join(outputDir, file.path);\n\n // Repair on-disk casing when an emitter renames a generated file in a\n // case-only way (e.g. `AuthenticationMfaFailed.kt` → `AuthenticationMFAFailed.kt`\n // after adding `MFA` to an acronym list). On case-insensitive filesystems\n // (APFS, NTFS) `writeFile` would otherwise reuse the existing inode and\n // preserve the stale casing — surfacing later as ktlint/eslint errors.\n await renameMismatchedCasing(fullPath);\n\n // Check if file already exists\n let existingContent: string | null = null;\n try {\n existingContent = await fs.readFile(fullPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n // New file → write in full\n if (existingContent === null) {\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // skipIfExists → hard skip, no merge (but ensure header is present).\n // JSON files are skipped from header injection because a leading `//`\n // comment makes the file invalid JSON.\n if (file.skipIfExists) {\n if (header && !existingContent.startsWith(header) && !file.path.endsWith('.json')) {\n await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n }\n result.skipped.push(file.path);\n continue;\n }\n\n // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n if (existingContent.includes('@oagen-ignore-file')) {\n result.ignored.push(file.path);\n continue;\n }\n\n // Don't merge test files into hand-written test files — generated tests are\n // designed for the standalone generated SDK and will have wrong\n // signatures/fixtures when merged into hand-written tests.\n // However, if the existing test file is itself auto-generated (has the oagen\n // header), allow overwriteExisting to take effect so new methods get coverage.\n const adapter = language ? getMergeAdapter(language) : undefined;\n const isTestFile = adapter?.testFilePatterns\n ? adapter.testFilePatterns.some((p) => p.test(file.path))\n : isDefaultTestFile(file.path);\n if (isTestFile) {\n const isExistingAutoGenerated = header && existingContent.startsWith(header);\n if (!isExistingAutoGenerated && !file.overwriteExisting) {\n result.skipped.push(file.path);\n continue;\n }\n // Auto-generated test file or overwriteExisting — fall through to overwriteExisting / identical checks\n }\n\n // Identical content → no-op\n if (existingContent === file.content) {\n result.identical.push(file.path);\n continue;\n }\n\n // Force overwrite — but preserve any @oagen-ignore regions from existing content\n if (file.overwriteExisting) {\n const content =\n existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n : file.content;\n await fs.writeFile(fullPath, content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // JSON files → deep merge preserving existing keys\n if (file.path.endsWith('.json')) {\n try {\n const existingJson = JSON.parse(existingContent);\n const generatedJson = JSON.parse(file.content);\n const merged = deepMergeJson(existingJson, generatedJson);\n const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n if (mergedContent === existingContent) {\n result.identical.push(file.path);\n } else {\n await fs.writeFile(fullPath, mergedContent, 'utf-8');\n result.merged.push(file.path);\n }\n } catch {\n // Parse failed — fall back to overwrite\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n }\n continue;\n }\n\n // Source files with grammar → AST-level merge\n if (language && hasGrammar(language)) {\n try {\n const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n // Ensure header is present on merged content\n let finalContent = mergeResult.content;\n if (header && !finalContent.startsWith(header)) {\n finalContent = header + '\\n\\n' + finalContent;\n }\n\n if (!mergeResult.changed && finalContent === existingContent) {\n result.identical.push(file.path);\n continue;\n }\n\n await fs.writeFile(fullPath, finalContent, 'utf-8');\n result.merged.push(file.path);\n continue;\n } catch (err) {\n // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n console.warn(\n `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n );\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n }\n\n // No grammar available → skip to avoid clobbering\n result.skipped.push(file.path);\n }\n\n return result;\n}\n\n/**\n * If a sibling exists with the same name except for letter case, rename it to\n * the requested casing. Uses a two-step rename via a temporary unique name so\n * case-insensitive filesystems (APFS on macOS, NTFS on Windows) actually\n * update the entry — `rename('Foo', 'FOO')` is a no-op on those systems.\n */\nasync function renameMismatchedCasing(fullPath: string): Promise<void> {\n const dir = path.dirname(fullPath);\n const target = path.basename(fullPath);\n let entries: string[];\n try {\n entries = await fs.readdir(dir);\n } catch {\n return;\n }\n if (entries.includes(target)) return;\n const targetLower = target.toLowerCase();\n const mismatch = entries.find((e) => e.toLowerCase() === targetLower);\n if (!mismatch) return;\n const oldPath = path.join(dir, mismatch);\n const tempPath = path.join(dir, `.oagen-case-${process.pid}-${Date.now()}-${target}`);\n await fs.rename(oldPath, tempPath);\n await fs.rename(tempPath, fullPath);\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n return (\n /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n filePath.endsWith('_test.go') ||\n filePath.endsWith('_test.rb') ||\n filePath.endsWith('_spec.rb') ||\n /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n filePath.endsWith('_test.py') ||\n filePath.endsWith('Test.php') ||\n filePath.endsWith('_test.rs') ||\n /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n existingContent: string,\n generatedContent: string,\n language: string,\n): Promise<string> {\n const existingLines = existingContent.split('\\n');\n const generatedLines = generatedContent.split('\\n');\n\n // 1. Extract ignore blocks, their containing class, and the anchor line\n // (first non-blank line after the block in the existing file).\n const blocks: { containingClass: string; containingScope: string; lines: string[]; anchor: string }[] = [];\n for (let i = 0; i < existingLines.length; i++) {\n if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n const startIdx = i;\n while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n let anchor = '';\n for (let a = i + 1; a < existingLines.length; a++) {\n if (existingLines[a].trim()) {\n anchor = existingLines[a].trimStart();\n break;\n }\n }\n blocks.push({\n containingClass: findContainingClass(existingLines, startIdx),\n containingScope: findContainingDescribeScope(existingLines, startIdx),\n lines: existingLines.slice(startIdx, i + 1),\n anchor,\n });\n }\n if (blocks.length === 0) return generatedContent;\n\n // 2. Splice extra imports from existing into generated.\n // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n // generator itself emitted: we are about to re-insert the on-disk versions,\n // and if we left the generator's seed blocks in place we'd end up with two\n // copies of every ignore block per regeneration (monotonically growing).\n const result = stripIgnoreRegions(generatedLines);\n spliceExtraImports(existingLines, result);\n\n // 3. Build class-end map from the generated content (after import splicing)\n // via tree-sitter for accurate boundary detection.\n const genSource = result.join('\\n');\n const classEndLines = await extractClassEndLines(genSource, language);\n\n // 4. Group ignore blocks by class and determine insertion points\n const blocksByClass = new Map<string, Array<{ containingScope: string; lines: string[]; anchor: string }>>();\n for (const b of blocks) {\n if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n blocksByClass.get(b.containingClass)!.push({\n containingScope: b.containingScope,\n lines: b.lines,\n anchor: b.anchor,\n });\n }\n\n // 4a. Handle replacement blocks: ignore blocks that redefine their\n // containing class replace the generated class entirely.\n // Also handles top-level blocks (no containing class) that define\n // a class matching one in the generated content.\n const replacedClasses = new Set<string>();\n const handledBlockKeys = new Set<string>();\n const replacements: {\n startLine: number;\n endLine: number;\n content: string[];\n }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n // Determine the target class for replacement. When the block has a\n // containing class, we check if the block redefines that class. When\n // there is no containing class (top-level ignore block), we look for a\n // class definition inside the block that matches a generated class.\n let targetClass = className;\n if (!targetClass) {\n for (const entry of classBlocks) {\n for (const l of entry.lines) {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n if (m && classEndLines.has(m[1])) {\n targetClass = m[1];\n break;\n }\n }\n if (targetClass) break;\n }\n }\n if (!targetClass) continue;\n const isReplacement = classBlocks.some((entry) =>\n entry.lines.some((l) => {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n return m?.[1] === targetClass;\n }),\n );\n if (!isReplacement) continue;\n const info = classEndLines.get(targetClass);\n if (!info) continue;\n const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n if (startLine < 0) continue;\n const content: string[] = [];\n for (const entry of classBlocks) {\n content.push('');\n content.push(...entry.lines);\n }\n replacements.push({ startLine, endLine: info.bodyEndLine, content });\n replacedClasses.add(targetClass);\n handledBlockKeys.add(className);\n }\n // Apply replacements bottom-up to preserve line indices\n replacements.sort((a, b) => b.startLine - a.startLine);\n for (const rep of replacements) {\n result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n }\n\n // 4a-bis. Top-level declarations protected by ignore regions win over their\n // generated counterparts. For each top-level block, drop generated\n // declarations (interface/type/const/function/…) whose names are\n // declared inside the block; the block content replaces the first\n // such declaration in place. Without this, every regeneration\n // re-emits a duplicate of each region-protected declaration.\n let regionDeclarationEdits = 0;\n {\n const topLevelEntries = blocksByClass.get('');\n if (topLevelEntries) {\n // When 4a already placed the top-level blocks (as part of a class\n // replacement), only delete generated duplicates — never re-insert.\n const alreadyPlaced = handledBlockKeys.has('');\n const remaining: typeof topLevelEntries = [];\n for (const entry of topLevelEntries) {\n const outcome = await applyRegionDeclarationOverride(result, entry.lines, language, !alreadyPlaced);\n if (outcome.edited) regionDeclarationEdits++;\n if (!alreadyPlaced && !outcome.placed) remaining.push(entry);\n }\n if (!alreadyPlaced) {\n if (remaining.length === 0) {\n blocksByClass.delete('');\n } else {\n blocksByClass.set('', remaining);\n }\n }\n }\n }\n\n // 4b. Standard insertions for non-replacement blocks\n // Rebuild class end lines if replacements shifted line numbers.\n let effectiveClassEndLines = classEndLines;\n if (replacedClasses.size > 0 || regionDeclarationEdits > 0) {\n effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n }\n\n const insertions: { line: number; order: number; content: string[] }[] = [];\n let insertionOrder = 0;\n for (const [className, classBlocks] of blocksByClass) {\n if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n const info = className ? effectiveClassEndLines.get(className) : undefined;\n\n // Insert each block individually so each can use its own anchor.\n for (const entry of classBlocks) {\n let insertLine: number | undefined;\n\n // Try anchor-based positioning: find the first line in the generated\n // file whose trimmed-start content matches the anchor (the first\n // non-blank line that followed this block in the existing file).\n // Skip anchors that are just punctuation (braces, etc.) since they\n // match too many locations. Accept doc comment starters (/** /// #)\n // as valid anchors since they're structurally meaningful.\n // Also skip bare language keywords (`end`, `end;`, `end)`) that appear\n // on many lines and would match the wrong location (e.g. nesting the\n // block inside a Ruby method body instead of at class level).\n const isAmbiguousAnchor = /^end[;)\\s]*$/.test(entry.anchor);\n if (\n entry.anchor &&\n !entry.anchor.includes('@oagen-ignore') &&\n !isAmbiguousAnchor &&\n /[a-zA-Z]|^\\/\\*|^\\/\\//.test(entry.anchor)\n ) {\n for (let li = 0; li < result.length; li++) {\n if (result[li].trimStart() === entry.anchor) {\n insertLine = li;\n break;\n }\n }\n }\n\n // Fallback: class body end, or for top-level import blocks, after the\n // last import line (so they stay near the top of the file, not at the\n // bottom where they'd trigger E402 lint errors).\n if (insertLine === undefined) {\n if (info) {\n insertLine = info.bodyEndLine;\n } else {\n const scopeEndLine = entry.containingScope\n ? findDescribeScopeEndLine(result, entry.containingScope)\n : undefined;\n const blockHasImportsFallback = entry.lines.some((l: string) => /^\\s*(import|from)\\s/.test(l));\n if (scopeEndLine !== undefined) {\n insertLine = scopeEndLine;\n } else if (blockHasImportsFallback || hasTopLevelDeclaration(entry.lines)) {\n let lastImportLine = 0;\n for (let li = 0; li < result.length; li++) {\n const trimmed = result[li].trimStart();\n if (/^(import|from)\\s/.test(trimmed)) lastImportLine = li + 1;\n }\n insertLine = lastImportLine;\n } else {\n insertLine = result.length;\n }\n }\n }\n\n // When inserting an import-containing ignore block, move up past\n // blank separator lines so the block sits flush with surrounding\n // imports (e.g., Kotlin's ktlint forbids blank lines within import\n // blocks).\n const blockHasImports = entry.lines.some((l: string) => /^\\s*import\\s/.test(l));\n if (blockHasImports) {\n while (\n insertLine >= 2 &&\n result[insertLine - 1]?.trim() === '' &&\n /^\\s*(import|using|from)\\s/.test(result[insertLine - 2] ?? '')\n ) {\n insertLine--;\n }\n }\n\n // Skip the leading blank line when the block is adjacent to imports\n // or already preceded by a blank line (avoids double-blank-line gaps).\n // Exclude C# `using` directives — StyleCop SA1515 requires a blank\n // line before comments, so collapsing breaks the build.\n const prevLine = insertLine > 0 ? (result[insertLine - 1]?.trimStart() ?? '') : '';\n const prevIsImport = /^import\\s/.test(prevLine) || /^from\\s/.test(prevLine);\n const prevIsBlank = insertLine > 0 && prevLine === '';\n const blockContent = prevIsImport || prevIsBlank ? [...entry.lines] : ['', ...entry.lines];\n // Add a trailing blank line when the next line is a doc comment\n // (C# SA1514 requires a blank line before `///` doc headers).\n const nextLine = result[insertLine]?.trimStart() ?? '';\n if (nextLine.startsWith('///')) {\n blockContent.push('');\n }\n insertions.push({ line: insertLine, order: insertionOrder++, content: blockContent });\n }\n }\n\n // Apply bottom-up to preserve line indices. Blocks with the same insertion\n // line must be applied in reverse discovery order because each splice inserts\n // at the same index; otherwise repeated generation flips their order.\n insertions.sort((a, b) => b.line - a.line || b.order - a.order);\n for (const ins of insertions) {\n result.splice(ins.line, 0, ...ins.content);\n }\n\n removeDuplicateImportsCoveredByIgnoreBlocks(result);\n\n return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n // Drop a preceding blank line if we have one queued up — otherwise\n // regen leaves a stray blank line above the spliced-in block.\n while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n if (/^\\S/.test(lines[lineIdx] ?? '')) return '';\n // Allow leading whitespace and language-specific modifiers before `class`.\n // Covers: `public class Foo` (C#/Java), `export class Foo` (TS),\n // `class Foo` (Python/Ruby), `internal sealed class Foo` (C#), etc.\n for (let j = lineIdx - 1; j >= 0; j--) {\n const m = lines[j].match(\n /^\\s*(?:(?:export|public|private|protected|internal|abstract|sealed|static|partial)\\s+)*class\\s+(\\w+)/,\n );\n if (m) return m[1];\n }\n return '';\n}\n\nfunction findContainingDescribeScope(lines: string[], lineIdx: number): string {\n const markerLine = lines[lineIdx] ?? '';\n if (/^\\S/.test(markerLine)) return '';\n const markerIndent = leadingSpaces(markerLine);\n for (let j = lineIdx - 1; j >= 0; j--) {\n const line = lines[j];\n const indent = leadingSpaces(line);\n if (indent >= markerIndent) continue;\n const match = line.match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n if (match) return match[2];\n if (/^\\s*(?:export\\s+)?class\\s+\\w+/.test(line)) return '';\n }\n return '';\n}\n\nfunction findDescribeScopeEndLine(lines: string[], scopeName: string): number | undefined {\n for (let i = 0; i < lines.length; i++) {\n const match = lines[i].match(/^\\s*describe\\((['\"`])(.+?)\\1\\s*,/);\n if (!match || match[2] !== scopeName) continue;\n\n let depth = 0;\n for (let j = i; j < lines.length; j++) {\n depth += countChar(lines[j], '{');\n depth -= countChar(lines[j], '}');\n if (j > i && depth <= 0) return j;\n }\n }\n return undefined;\n}\n\nfunction leadingSpaces(line: string): number {\n return line.match(/^\\s*/)?.[0].length ?? 0;\n}\n\nfunction countChar(line: string, char: string): number {\n return [...line].filter((c) => c === char).length;\n}\n\nfunction hasTopLevelDeclaration(lines: string[]): boolean {\n return lines.some((line) =>\n /^(?:export\\s+)?(?:interface|type|class|function|const|let|var|enum)\\s+\\w+/.test(line.trim()),\n );\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n // Match optional indentation so Ruby/Python nested classes are found.\n const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n for (let i = beforeLine - 1; i >= 0; i--) {\n if (!classPattern.test(lines[i])) continue;\n // Scan backward past decorators\n let start = i;\n while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n start--;\n }\n return start;\n }\n return -1;\n}\n\n// --- region-protected top-level declaration overrides ---\n\n/**\n * Conservative top-level declaration matcher for ignore-block content.\n * Matches column-0 declarations like `export interface X`, `type X = …`,\n * `const X = …`, `function X(…)`, `class X` (export optional). Names found\n * here are only acted on when the language's merge adapter also reports a\n * generated top-level statement with the same key, so false positives are\n * filtered by the real parser.\n */\nconst REGION_DECLARATION_PATTERN =\n /^(?:export\\s+)?(?:declare\\s+)?(?:interface|type|enum|class|const|let|var|async\\s+function|function)\\s+([A-Za-z_$][\\w$]*)/;\n\n/** Extract top-level symbol names declared inside an ignore block's lines. */\nfunction collectRegionDeclaredNames(blockLines: string[]): Set<string> {\n const names = new Set<string>();\n for (const line of blockLines) {\n if (line.includes('@oagen-ignore')) continue;\n const m = line.match(REGION_DECLARATION_PATTERN);\n if (m) names.add(m[1]);\n }\n return names;\n}\n\n/** Inclusive line ranges of `@oagen-ignore-start`..`@oagen-ignore-end` regions. */\nfunction collectIgnoreRegionLineRanges(lines: string[]): Array<{ start: number; end: number }> {\n const ranges: Array<{ start: number; end: number }> = [];\n let start = -1;\n for (let i = 0; i < lines.length; i++) {\n if (start === -1 && lines[i].includes('@oagen-ignore-start')) {\n start = i;\n continue;\n }\n if (start !== -1 && lines[i].includes('@oagen-ignore-end')) {\n ranges.push({ start, end: i });\n start = -1;\n }\n }\n return ranges;\n}\n\n/**\n * Walk upward from a declaration's first line over its contiguous comment\n * block (doc comment), so the comment is dropped together with the\n * declaration. Stops at blank lines, region markers, and line 0 (a comment\n * on line 0 is the file header, not a docstring).\n */\nfunction extendOverPrecedingComments(lines: string[], startLine: number): number {\n let s = startLine;\n while (s > 1) {\n const prev = lines[s - 1].trim();\n if (prev === '' || prev.includes('@oagen-ignore')) break;\n const isComment = prev.startsWith('//') || prev.startsWith('/*') || prev.startsWith('*') || prev.startsWith('#');\n if (!isComment) break;\n s--;\n }\n return s;\n}\n\n/**\n * Drop generated top-level declarations that are redeclared inside an ignore\n * block (\"region wins\"). When `placeBlock` is set and at least one generated\n * declaration matches, the block's lines replace the first match in place\n * (mirroring the class-replacement behavior above); any further matches are\n * deleted. Mutates `result` in place.\n *\n * Returns `placed` (the block content now lives in `result` and must not be\n * inserted again) and `edited` (line numbers shifted).\n */\nasync function applyRegionDeclarationOverride(\n result: string[],\n blockLines: string[],\n language: string,\n placeBlock: boolean,\n): Promise<{ placed: boolean; edited: boolean }> {\n const names = collectRegionDeclaredNames(blockLines);\n if (names.size === 0) return { placed: false, edited: false };\n\n const source = result.join('\\n');\n let parsed;\n try {\n parsed = await extractStatements(source, language);\n } catch {\n return { placed: false, edited: false };\n }\n\n const regionRanges = collectIgnoreRegionLineRanges(result);\n const inRegion = (line: number) => regionRanges.some((r) => line >= r.start && line <= r.end);\n\n const spans: Array<{ start: number; end: number }> = [];\n for (const stmt of parsed.statements) {\n if (stmt.kind !== 'declaration' || !stmt.key || !names.has(stmt.key)) continue;\n // Locate the statement's line span; skip occurrences inside ignore\n // regions (those ARE the protected content).\n let idx = source.indexOf(stmt.text);\n let startLine = -1;\n while (idx !== -1) {\n const line = source.slice(0, idx).split('\\n').length - 1;\n if (!inRegion(line)) {\n startLine = line;\n break;\n }\n idx = source.indexOf(stmt.text, idx + 1);\n }\n if (startLine === -1) continue;\n const endLine = startLine + stmt.text.split('\\n').length - 1;\n spans.push({ start: extendOverPrecedingComments(result, startLine), end: endLine });\n }\n if (spans.length === 0) return { placed: false, edited: false };\n\n spans.sort((a, b) => a.start - b.start);\n\n // Delete all matches after the first, bottom-up to preserve indices.\n for (let i = spans.length - 1; i >= 1; i--) {\n const span = spans[i];\n let deleteCount = span.end - span.start + 1;\n // Collapse the blank separator the deletion leaves behind.\n const prevBlank = span.start === 0 || (result[span.start - 1] ?? '').trim() === '';\n const nextBlank = (result[span.end + 1] ?? '').trim() === '';\n if (prevBlank && nextBlank && span.end + 1 < result.length) deleteCount++;\n result.splice(span.start, deleteCount);\n }\n\n const first = spans[0];\n if (placeBlock) {\n result.splice(first.start, first.end - first.start + 1, ...blockLines);\n return { placed: true, edited: true };\n }\n\n let deleteCount = first.end - first.start + 1;\n const prevBlank = first.start === 0 || (result[first.start - 1] ?? '').trim() === '';\n const nextBlank = (result[first.end + 1] ?? '').trim() === '';\n if (prevBlank && nextBlank && first.end + 1 < result.length) deleteCount++;\n result.splice(first.start, deleteCount);\n return { placed: false, edited: true };\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n const byModule = new Map<string, Set<string>>();\n for (let i = 0; i < lines.length; i++) {\n if (!/^from\\s+/.test(lines[i])) continue;\n\n let fullText = lines[i];\n if (fullText.includes('(') && !fullText.includes(')')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes(')')) break;\n }\n }\n\n const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n if (!match) continue;\n\n const mod = match[1];\n if (!byModule.has(mod)) byModule.set(mod, new Set());\n for (const id of match[2]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)) {\n byModule.get(mod)!.add(id);\n }\n }\n return byModule;\n}\n\n/**\n * Collected TypeScript imports grouped by form. Each map keys on the module\n * specifier (e.g. `./foo`, `node:fs`).\n */\ninterface TsImports {\n /** `import { X, Y } from 'module'` — module → identifier names. */\n named: Map<string, Set<string>>;\n /** `import type { X } from 'module'` — module → identifier names. */\n typeOnly: Map<string, Set<string>>;\n /** `import X from 'module'` or `import type X from 'module'` — module → name. */\n defaults: Map<string, string>;\n /** `import * as X from 'module'` — module → namespace alias name. */\n namespaces: Map<string, string>;\n /** `import 'module'` — modules imported for side effects only. */\n sideEffects: Set<string>;\n}\n\n/**\n * Collect TypeScript imports, grouped by form. Handles single-line and\n * multi-line `{ … }` named imports. Disjoint from Python's `from X import Y`\n * syntax so this can be called in parallel with `collectFromImports`.\n */\nfunction collectTsImports(lines: string[]): TsImports {\n const out: TsImports = {\n named: new Map(),\n typeOnly: new Map(),\n defaults: new Map(),\n namespaces: new Map(),\n sideEffects: new Set(),\n };\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!/^import(\\s|$)/.test(trimmed)) continue;\n\n // Accumulate multi-line `{ … }` imports.\n let fullText = lines[i];\n if (fullText.includes('{') && !fullText.includes('}')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes('}')) break;\n }\n }\n\n const normalized = fullText.replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n\n // `import 'module'`\n let m = normalized.match(/^import\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.sideEffects.add(m[1]);\n continue;\n }\n\n // `import * as X from 'module'`\n m = normalized.match(/^import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.namespaces.set(m[2], m[1]);\n continue;\n }\n\n // `import [Default,] { X, Y as Z } from 'module'` or `import type { X } from 'module'`\n m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n const isTypeOnly = !!m[1];\n const defaultName = m[2];\n const namesRaw = m[3];\n const mod = m[4];\n if (defaultName) out.defaults.set(mod, defaultName);\n const names = namesRaw\n .split(',')\n .map((s) => s.trim().replace(/\\s+as\\s+\\w+$/, ''))\n .filter(Boolean);\n for (const rawName of names) {\n const isInlineTypeOnly = rawName.startsWith('type ');\n const name = rawName.replace(/^type\\s+/, '');\n const target = isTypeOnly || isInlineTypeOnly ? out.typeOnly : out.named;\n if (!target.has(mod)) target.set(mod, new Set());\n target.get(mod)!.add(name);\n }\n continue;\n }\n\n // `import X from 'module'` or `import type X from 'module'`\n m = normalized.match(/^import\\s+(?:type\\s+)?(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]$/);\n if (m) {\n out.defaults.set(m[2], m[1]);\n continue;\n }\n }\n\n return out;\n}\n\n/**\n * Remove the given symbols from generated `import type` bindings, in place.\n *\n * Called when an existing *value* import for the same symbol is being spliced\n * back into the file. A value import satisfies both runtime and type uses, so\n * leaving the generated `import type { X }` would re-declare `X` (TS2300\n * duplicate identifier). Callers guarantee every symbol here is absent from\n * generated *value* imports, so each occurrence is type-only and safe to drop.\n *\n * Handles whole-line `import type { … }` and inline `import { …, type X }`,\n * single- or multi-line. A statement whose bindings all get stripped is\n * removed entirely.\n */\nfunction dropGeneratedTypeOnlyBindings(resultLines: string[], symbols: Set<string>): void {\n if (symbols.size === 0) return;\n const out: string[] = [];\n for (let i = 0; i < resultLines.length; i++) {\n const line = resultLines[i];\n const trimmed = line.trim();\n // Only named imports (with a brace) can carry the symbols we strip.\n if (!/^import\\b/.test(trimmed) || !trimmed.includes('{')) {\n out.push(line);\n continue;\n }\n // Gather the full (possibly multi-line) `{ … }` statement.\n const span = [line];\n while (!span.join(' ').includes('}') && i + 1 < resultLines.length) {\n i++;\n span.push(resultLines[i]);\n }\n const normalized = span.join(' ').replace(/\\s+/g, ' ').trim().replace(/;\\s*$/, '');\n const m = normalized.match(/^import\\s+(type\\s+)?(?:(\\w+)\\s*,\\s*)?\\{\\s*([^}]*)\\s*\\}\\s+from\\s+(['\"][^'\"]+['\"])$/);\n if (!m) {\n for (const s of span) out.push(s);\n continue;\n }\n const isTypeOnly = !!m[1];\n const defaultName = m[2];\n const items = m[3]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const modQuoted = m[4];\n const kept = items.filter((raw) => {\n const isTypeBinding = isTypeOnly || raw.startsWith('type ');\n const bare = raw.replace(/^type\\s+/, '');\n return !(isTypeBinding && symbols.has(bare));\n });\n if (kept.length === items.length) {\n // Nothing stripped — preserve the original lines verbatim.\n for (const s of span) out.push(s);\n continue;\n }\n if (kept.length === 0 && !defaultName) continue; // statement fully emptied\n const lead = line.match(/^(\\s*)/)?.[1] ?? '';\n const prefix = isTypeOnly ? 'import type ' : 'import ';\n const defaultPart = defaultName ? `${defaultName}, ` : '';\n out.push(`${lead}${prefix}${defaultPart}{ ${kept.join(', ')} } from ${modQuoted};`);\n }\n resultLines.splice(0, resultLines.length, ...out);\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles:\n *\n * - Python: `import X` and `from X import Y`\n * - TypeScript: `import { X } from 'module'`, `import type { X } from 'module'`,\n * `import X from 'module'`, `import * as X from 'module'`, `import 'module'`\n * - PHP: `use Foo\\Bar;` and `use Foo\\Bar as Baz;` (namespace-qualified only)\n * - Ruby: `require '…'` and `require_relative '…'`\n *\n * Mutates `resultLines` in place.\n */\nfunction filterOutIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\nfunction collectIgnoreRegionUsageText(lines: string[]): string {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n continue;\n }\n if (!skipping) continue;\n if (/^\\s*(import|from)\\s/.test(line)) continue;\n out.push(line);\n if (line.includes('@oagen-ignore-end')) skipping = false;\n }\n return out.join('\\n');\n}\n\nfunction removeDuplicateImportsCoveredByIgnoreBlocks(lines: string[]): void {\n const ignoredImports = new Set<string>();\n const importStatements = collectImportStatements(lines);\n for (const stmt of importStatements) {\n if (stmt.inIgnore) ignoredImports.add(normalizeImportStatement(stmt.lines));\n }\n if (ignoredImports.size === 0) return;\n\n for (const stmt of [...importStatements].reverse()) {\n if (stmt.inIgnore) continue;\n if (ignoredImports.has(normalizeImportStatement(stmt.lines))) {\n lines.splice(stmt.start, stmt.end - stmt.start + 1);\n }\n }\n}\n\nfunction collectImportStatements(\n lines: string[],\n): Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> {\n const statements: Array<{ start: number; end: number; lines: string[]; inIgnore: boolean }> = [];\n let inIgnore = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!inIgnore && line.includes('@oagen-ignore-start')) {\n inIgnore = true;\n continue;\n }\n if (inIgnore && line.includes('@oagen-ignore-end')) {\n inIgnore = false;\n continue;\n }\n if (!isImportLine(line)) continue;\n\n const start = i;\n let end = i;\n const statementLines = [line];\n const opens = (line.match(/[({]/g) ?? []).length;\n const closes = (line.match(/[)}]/g) ?? []).length;\n if (opens > closes) {\n while (end + 1 < lines.length) {\n end++;\n statementLines.push(lines[end]);\n if ((lines[end].match(/[)}]/g) ?? []).length > 0 && /\\bfrom\\b/.test(lines[end])) break;\n }\n i = end;\n }\n statements.push({ start, end, lines: statementLines, inIgnore });\n }\n return statements;\n}\n\nfunction normalizeImportStatement(lines: string[]): string {\n return lines.join('\\n').replace(/,\\s*}/g, ' }').replace(/\\s+/g, ' ').trim();\n}\n\nfunction isImportLine(line: string): boolean {\n const trimmed = line.trim();\n return (\n /^import(\\s|$)/.test(trimmed) ||\n /^from\\s+/.test(trimmed) ||\n /^use\\s+[\\w\\\\]/.test(trimmed) ||\n /^require(_relative)?\\s+['\"]/.test(trimmed)\n );\n}\n\nfunction identifierUsed(source: string, identifier: string): boolean {\n return new RegExp(`\\\\b${identifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`).test(source);\n}\n\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n // Imports inside @oagen-ignore regions are converted into normal imports\n // only when non-import ignore content still references them. This prevents\n // stale import-only ignore blocks from creating duplicate or unused imports.\n const existingOutsideIgnore = filterOutIgnoreRegions(existingLines);\n const ignoreRegionText = collectIgnoreRegionUsageText(existingLines);\n\n // Python-style `import hashlib`. Excludes TS forms like `import X from '…'`\n // (have a `from` clause) and TS multi-line type imports whose first line is\n // `import type {` (have a brace) — both are handled by the TS collector\n // below.\n const isPythonSimpleImport = (l: string) => /^import\\s+\\w/.test(l) && !/\\sfrom\\s/.test(l) && !/[{}]/.test(l);\n\n // Simple imports (import hashlib, import json, …)\n const existingSimple = new Set(existingOutsideIgnore.filter(isPythonSimpleImport).map((l) => l.trim()));\n const generatedSimple = new Set(resultLines.filter(isPythonSimpleImport).map((l) => l.trim()));\n const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n // From-imports — compare by module and find extra identifiers\n const existingFrom = collectFromImports(existingOutsideIgnore);\n const generatedFrom = collectFromImports(resultLines);\n\n // Build a set of all identifiers imported by the generated file (across all modules)\n // so we can detect when an existing barrel import's identifiers are covered by\n // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n const allGeneratedIds = new Set<string>();\n for (const ids of generatedFrom.values()) {\n for (const id of ids) allGeneratedIds.add(id);\n }\n\n const extraFromLines: string[] = [];\n for (const [mod, existIds] of existingFrom) {\n const genIds = generatedFrom.get(mod);\n if (!genIds) {\n // The exact module isn't in the generated file — but check whether every\n // identifier is already imported from a different (e.g., more-specific) module.\n const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n } else {\n const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n }\n }\n\n // TypeScript imports.\n const existingTs = collectTsImports(existingOutsideIgnore);\n const generatedTs = collectTsImports(resultLines);\n const extraTsLines: string[] = [];\n\n // Bindings the generated file imports anywhere, split by capability.\n //\n // `allGeneratedTsIds` — every binding regardless of module. The generator\n // frequently imports a symbol from a concrete file\n // (`./interfaces/connection.interface`) while the existing hand-written file\n // imported the same symbol from a barrel (`./interfaces`). Splicing the\n // barrel form back in would re-declare the binding (TS2300 duplicate\n // identifier), so a symbol already in scope satisfies a *type* use and is\n // never re-imported as a type even from a different specifier.\n //\n // `generatedValueIds` — only runtime-capable bindings (named / default /\n // namespace, never `import type`). A *value* use is satisfied only by one of\n // these: an `import type` binding is erased at compile time and cannot back a\n // runtime reference inside a preserved region. So a generated `import type`\n // must NOT suppress an existing value import of the same symbol.\n const allGeneratedTsIds = new Set<string>();\n const generatedValueIds = new Set<string>();\n for (const ids of generatedTs.named.values())\n for (const id of ids) {\n allGeneratedTsIds.add(id);\n generatedValueIds.add(id);\n }\n for (const ids of generatedTs.typeOnly.values()) for (const id of ids) allGeneratedTsIds.add(id);\n for (const name of generatedTs.defaults.values()) {\n allGeneratedTsIds.add(name);\n generatedValueIds.add(name);\n }\n for (const name of generatedTs.namespaces.values()) {\n allGeneratedTsIds.add(name);\n generatedValueIds.add(name);\n }\n\n // Symbols the generated file imports type-only that we are nonetheless\n // re-splicing as value imports (because a preserved region needs the runtime\n // binding). The spliced value import also covers the type use, so the\n // generated `import type` for the symbol must be dropped or the two collide\n // (TS2300). Collected during the loops below, applied just before splicing.\n const reclaimedValueIds = new Set<string>();\n const generatedHasValue = (id: string): boolean => generatedValueIds.has(id);\n const generatedHasTypeOnly = (id: string): boolean => allGeneratedTsIds.has(id) && !generatedValueIds.has(id);\n\n for (const mod of existingTs.sideEffects) {\n if (!generatedTs.sideEffects.has(mod)) extraTsLines.push(`import '${mod}';`);\n }\n for (const [mod, name] of existingTs.defaults) {\n if (generatedTs.defaults.has(mod)) continue;\n if (!identifierUsed(ignoreRegionText, name)) continue;\n if (generatedHasValue(name)) continue;\n if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n extraTsLines.push(`import ${name} from '${mod}';`);\n }\n for (const [mod, name] of existingTs.namespaces) {\n if (!identifierUsed(ignoreRegionText, name)) continue;\n if (generatedHasValue(name)) continue;\n if (generatedTs.namespaces.has(mod)) continue;\n if (generatedHasTypeOnly(name)) reclaimedValueIds.add(name);\n extraTsLines.push(`import * as ${name} from '${mod}';`);\n }\n for (const [mod, existIds] of existingTs.named) {\n const extra = [...existIds].filter((id) => !generatedHasValue(id) && identifierUsed(ignoreRegionText, id));\n for (const id of extra) if (generatedHasTypeOnly(id)) reclaimedValueIds.add(id);\n if (extra.length > 0) extraTsLines.push(`import { ${extra.join(', ')} } from '${mod}';`);\n }\n for (const [mod, existIds] of existingTs.typeOnly) {\n const extra = [...existIds].filter((id) => !allGeneratedTsIds.has(id) && identifierUsed(ignoreRegionText, id));\n if (extra.length > 0) extraTsLines.push(`import type { ${extra.join(', ')} } from '${mod}';`);\n }\n\n // Drop reclaimed symbols from generated `import type` lines so the value\n // imports spliced above do not duplicate them.\n dropGeneratedTypeOnlyBindings(resultLines, reclaimedValueIds);\n\n // PHP `use Foo\\Bar;` and `use Foo\\Bar as Baz;` — namespace-qualified only\n // (a backslash anywhere in the path) so this doesn't mistakenly hoist\n // single-segment in-class trait references like `use TraitName;`.\n const isPhpUseImport = (l: string) => /^use\\s+[\\w\\\\]+\\\\[\\w\\\\]*(\\s+as\\s+\\w+)?\\s*;?$/.test(l);\n const existingPhpUse = new Set(existingOutsideIgnore.filter(isPhpUseImport).map((l) => l.trim()));\n const generatedPhpUse = new Set(resultLines.filter(isPhpUseImport).map((l) => l.trim()));\n const extraPhpUse = [...existingPhpUse].filter((l) => !generatedPhpUse.has(l));\n\n // Ruby `require '...'` and `require_relative '...'`. Dedupe by (kind, path)\n // so quote style differs without producing duplicates — e.g. when the\n // emitter writes `require 'json'` but a Ruby formatter has rewritten the\n // on-disk copy to `require \"json\"`.\n const rubyRequireRe = /^(require(?:_relative)?)\\s+['\"]([^'\"]+)['\"]\\s*$/;\n const rubyRequireKey = (l: string): string | undefined => {\n const m = l.trim().match(rubyRequireRe);\n return m ? `${m[1]}\\t${m[2]}` : undefined;\n };\n const generatedRubyRequireKeys = new Set<string>();\n for (const l of resultLines) {\n const key = rubyRequireKey(l);\n if (key) generatedRubyRequireKeys.add(key);\n }\n const seenExistingKeys = new Set<string>();\n const extraRubyRequire: string[] = [];\n for (const l of existingOutsideIgnore) {\n const key = rubyRequireKey(l);\n if (!key) continue;\n if (generatedRubyRequireKeys.has(key)) continue;\n if (seenExistingKeys.has(key)) continue;\n seenExistingKeys.add(key);\n extraRubyRequire.push(l.trim());\n }\n\n const allExtra = [...extraSimple, ...extraFromLines, ...extraTsLines, ...extraPhpUse, ...extraRubyRequire];\n if (allExtra.length === 0) return;\n\n // Find last import line in resultLines (accounting for multiline imports).\n // Recognizes Python (`from X import Y`, `import X`), TS (`import …`), PHP\n // (`use …`), and Ruby (`require`, `require_relative`).\n const isImportStart = (l: string) =>\n /^\\s*import(\\s|$)/.test(l) ||\n /^from\\s+/.test(l) ||\n /^\\s*use\\s+[\\w\\\\]/.test(l) ||\n /^\\s*require(_relative)?\\s+['\"]/.test(l);\n let lastImportIdx = -1;\n for (let i = 0; i < resultLines.length; i++) {\n if (!isImportStart(resultLines[i])) continue;\n lastImportIdx = i;\n const opens = (resultLines[i].match(/[({]/g) ?? []).length;\n const closes = (resultLines[i].match(/[)}]/g) ?? []).length;\n if (opens > closes) {\n while (i + 1 < resultLines.length) {\n i++;\n lastImportIdx = i;\n if ((resultLines[i].match(/[)}]/g) ?? []).length > 0) break;\n }\n }\n }\n\n if (lastImportIdx >= 0) {\n resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n return;\n }\n\n // No import survived in the generated file (e.g. its only import was a\n // type-only line reclaimed above). Insert after any leading comment header\n // so the spliced imports still land at the top of the file.\n let insertAt = 0;\n let inBlockComment = false;\n for (let i = 0; i < resultLines.length; i++) {\n const t = resultLines[i].trim();\n if (inBlockComment) {\n insertAt = i + 1;\n if (t.includes('*/')) inBlockComment = false;\n continue;\n }\n if (t.startsWith('//')) {\n insertAt = i + 1;\n continue;\n }\n if (t.startsWith('/*')) {\n insertAt = i + 1;\n inBlockComment = !t.includes('*/');\n continue;\n }\n break; // first blank or code line — stop here\n }\n resultLines.splice(insertAt, 0, ...allExtra);\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Validate a `--services` selection and return it as a set of POST-MOUNT service\n * names for emitters to scope on.\n *\n * Scoped generation does NOT filter the IR: model placement, dedup/aliasing, and\n * shared-schema decisions are global computations over the full service/model set\n * (filtering them churns shared `common/` files). Instead the full spec flows to\n * the emitters unchanged and this set is passed as `ctx.scopedServices`; each\n * emitter gates only its per-service resource/test emission on it.\n *\n * Matching is on the POST-MOUNT name. Mount resolution never mutates\n * `spec.services` — the post-mount target lives on `ResolvedOperation.mountOn`\n * (`mountOn = hint?.mountOn ?? mountRules[service.name] ?? service.name`) — so the\n * post-mount name of a source service is derived here as\n * `mountRules[service.name] ?? service.name`. Selecting a target (e.g.\n * `DirectorySync`) is valid because every source tag that mounts into it\n * (`DirectoryUsers`, `DirectoryGroups`, …) shares that post-mount name, and the\n * emitters group resources by mount, so all siblings emit together.\n *\n * @param spec - The parsed API spec (never mutated; never filtered).\n * @param selected - Post-mount service names from `--services` (normalized/trimmed).\n * @param mountRules - Source-service-name → post-mount-target mappings.\n * @returns The validated selection as a `Set` of post-mount names.\n * @throws A `ConfigError` listing valid post-mount names when a selection is\n * unknown — scoped generation never silently emits the wrong set.\n */\n/**\n * Canonicalize a service name to a casing/separator-insensitive key so that\n * `MultiFactorAuth` (post-mount IR name), `multi_factor_auth` (snake-cased\n * manifest record), and `multiFactorAuth` (camel-cased manifest record) all\n * collapse to `multifactorauth`. Used to match a spec service against the\n * services a prior manifest recorded as already on disk, where the casing of\n * the recorded `service` field varies per emitter.\n */\nexport function canonicalServiceKey(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]/g, '');\n}\n\nexport function resolveScopedServices(\n spec: ApiSpec,\n selected: string[],\n mountRules?: Record<string, string>,\n): Set<string> {\n const mounts = mountRules ?? {};\n const postMountName = (name: string): string => mounts[name] ?? name;\n const validPostMount = new Set(spec.services.map((s) => postMountName(s.name)));\n const selectedSet = new Set(selected);\n\n const unknown = [...selectedSet].filter((s) => !validPostMount.has(s));\n if (unknown.length > 0) {\n const err = new Error(\n `Unknown --services: ${unknown.sort().join(', ')}. ` +\n `Valid post-mount services: ${[...validPostMount].sort().join(', ')}`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n\n return selectedSet;\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\nimport { canonicalServiceKey } from './scoped-services.js';\n\nexport function buildEmitterContext(\n spec: ApiSpec,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n scopedServices?: Set<string>;\n presentServiceKeys?: Set<string>;\n },\n): EmitterContext {\n const resolvedOperations = resolveOperations(spec, options.operationHints, options.mountRules);\n\n // In a scoped run, derive the model/enum allow-lists = names reachable from the\n // emit SURFACE (selected ∪ already-on-disk services) — the SAME set\n // generateAllFiles emits over (aggregateSurfaceServices). Emitters write a\n // model/enum FILE only when it is in these sets.\n //\n // This must match the surface, NOT the selection alone: a scoped run\n // regenerates every on-disk service's fixtures and the (wholesale) round-trip\n // test from the current spec. If the model/enum FILES were gated to the\n // selection only, a present service whose spec drifted (new field) kept a stale\n // model class while its regenerated fixture + round-trip test asserted the new\n // field — a guaranteed round-trip test failure. Gating on the surface\n // regenerates the present service's model in lockstep, keeping the tree\n // consistent. A service the spec has but this SDK never generated is still\n // excluded (not selected, not present), so no orphaned files leak in.\n let scopedModelNames: Set<string> | undefined;\n let scopedEnumNames: Set<string> | undefined;\n if (options.scopedServices && options.scopedServices.size > 0) {\n const scope = options.scopedServices;\n const present = options.presentServiceKeys ?? new Set<string>();\n const postMountOf = (service: Service): string =>\n resolvedOperations.find((r) => r.service.name === service.name)?.mountOn ?? service.name;\n const surfaceSourceServices = spec.services.filter((s) => {\n const postMount = postMountOf(s);\n return scope.has(postMount) || present.has(canonicalServiceKey(postMount));\n });\n const reachable = collectReferencedNames(surfaceSourceServices, spec.models, { preserveAllDiscriminated: false });\n scopedModelNames = reachable.models;\n scopedEnumNames = reachable.enums;\n }\n\n return {\n namespace: toSnakeCase(options.namespace),\n namespacePascal: options.namespace,\n spec,\n outputDir: options.outputDir,\n apiSurface: options.apiSurface,\n overlayLookup: options.overlayLookup,\n resolvedOperations,\n modelHints: options.modelHints,\n emitterOptions: options.emitterOptions,\n targetDir: options.target,\n priorTargetManifestPaths: options.priorTargetManifestPaths,\n scopedServices: options.scopedServices,\n presentServiceKeys: options.presentServiceKeys,\n scopedModelNames,\n scopedEnumNames,\n };\n}\n\n/**\n * The services an aggregate (barrel/client/test) generator may reference in a\n * scoped run: the selected services plus every service the prior manifest\n * recorded as already on disk. A service the spec just added that is neither\n * selected nor already generated is excluded — otherwise the client/barrels\n * would import a resource/model whose file this run does not emit (the orphaned\n * `agents/__init__.py → ._resource` class of build break).\n *\n * Outside a scoped run (full generation), every service is in surface.\n */\nexport function aggregateSurfaceServices(spec: ApiSpec, ctx: EmitterContext): Service[] {\n const scope = ctx.scopedServices;\n if (!scope || scope.size === 0) return spec.services;\n const present = ctx.presentServiceKeys ?? new Set<string>();\n const postMountOf = (service: Service): string =>\n ctx.resolvedOperations?.find((r) => r.service.name === service.name)?.mountOn ?? service.name;\n return spec.services.filter((s) => {\n const postMount = postMountOf(s);\n return scope.has(postMount) || present.has(canonicalServiceKey(postMount));\n });\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n services: Service[],\n models: Model[],\n opts: { preserveAllDiscriminated?: boolean } = {},\n): { models: Set<string>; enums: Set<string> } {\n // Default: preserve EVERY discriminated/event model as public surface (full\n // emission). Strict mode (`preserveAllDiscriminated: false`, used to compute a\n // scoped run's reachable set) skips that blanket and instead chases the mapping\n // variants of discriminated models that are actually reached — so a scoped\n // service doesn't pull in the entire unrelated event tree.\n const preserveAllDiscriminated = opts.preserveAllDiscriminated !== false;\n const referencedModels = new Set<string>();\n const referencedEnums = new Set<string>();\n\n const collectFromTypeRef = (ref: TypeRef): void => {\n walkTypeRef(ref, {\n model: (r) => referencedModels.add(r.name),\n enum: (r) => referencedEnums.add(r.name),\n });\n };\n\n // Seed: walk every operation's params, request body, response, errors, and pagination\n for (const service of services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectFromTypeRef(p.type);\n }\n if (op.requestBody) collectFromTypeRef(op.requestBody);\n collectFromTypeRef(op.response);\n if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n for (const err of op.errors) {\n if (err.type) collectFromTypeRef(err.type);\n }\n if (op.successResponses) {\n for (const sr of op.successResponses) {\n collectFromTypeRef(sr.type);\n }\n }\n }\n }\n\n // Preserve discriminated models as public SDK types even when no operation\n // returns them directly. This matters for event/webhook unions where the base\n // operation references a generic envelope but the variant structs are still\n // useful public surface.\n //\n // Also preserve the variants mapped from an `allOf [base, oneOf […]]` base\n // (carried as `Model.discriminator.mapping`). The base model is reached\n // through the operation; without explicitly chasing its mapping, the\n // variant structs would be unreachable and the dispatcher would dangle\n // imports.\n if (preserveAllDiscriminated) {\n for (const model of models) {\n if (isDiscriminatedModel(model)) {\n referencedModels.add(model.name);\n }\n const disc = model.discriminator;\n if (disc?.mapping) {\n for (const variantName of Object.values(disc.mapping)) {\n referencedModels.add(variantName);\n }\n }\n }\n }\n\n // Chase: transitively resolve model field references until stable\n const modelsByName = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const queue = [...referencedModels];\n while (queue.length > 0) {\n const name = queue.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const model = modelsByName.get(name);\n if (!model) continue;\n // A reached discriminated base pulls in its mapping variants (the dispatcher\n // would otherwise dangle). In full mode this is redundant with the blanket\n // pass above; in strict mode it is the only path that includes variants.\n const disc = model.discriminator;\n if (disc?.mapping) {\n for (const variantName of Object.values(disc.mapping)) {\n if (!referencedModels.has(variantName)) {\n referencedModels.add(variantName);\n queue.push(variantName);\n }\n }\n }\n for (const field of model.fields) {\n collectFromTypeRef(field.type);\n // If new models were discovered, enqueue them\n for (const m of referencedModels) {\n if (!visited.has(m)) queue.push(m);\n }\n }\n }\n\n return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n return model.fields.some(\n (field) =>\n (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n );\n}\n\n/**\n * Collect all generated files from an emitter (no headers, no path prefixes).\n *\n * A full run emits over the whole spec. A scoped (`--services`) run still emits\n * model placement, dedup, the root client, and aggregate/barrel files\n * byte-identically for every service ALREADY on disk (plus the brand-new\n * selected service, which is wired into the client automatically) — but it\n * narrows that surface to `selected ∪ already-on-disk` services\n * (`aggregateSurfaceServices`). A service the spec just added that is neither\n * selected nor already generated is dropped from the surface entirely, so its\n * models/discriminators are not pulled into reachability and barrels/the client\n * never import a resource this run does not emit. The emitters additionally\n * consult `ctx.scopedServices` to emit only the selected services' per-service\n * resource/test files.\n */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n const scoped = !!ctx.scopedServices && ctx.scopedServices.size > 0;\n const surfaceServices = aggregateSurfaceServices(spec, ctx);\n // In a scoped run, restrict the blanket discriminated/event preservation to\n // models reachable from the in-surface services; otherwise an out-of-scope,\n // never-generated service's discriminated models (e.g. AgentRegistration*)\n // would still be force-included and emit orphaned converters/variants.\n const referenced = collectReferencedNames(surfaceServices, spec.models, {\n preserveAllDiscriminated: !scoped,\n });\n const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n const surfaceSpec: ApiSpec = { ...spec, services: surfaceServices };\n const reachableSpec: ApiSpec = { ...surfaceSpec, models: reachableModels, enums: reachableEnums };\n\n return [\n ...emitter.generateModels(reachableModels, ctx),\n ...emitter.generateEnums(reachableEnums, ctx),\n ...emitter.generateResources(surfaceServices, ctx),\n ...emitter.generateClient(surfaceSpec, ctx),\n ...emitter.generateErrors(ctx),\n ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n ...emitter.generateTests(reachableSpec, ctx),\n ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n return files.map((f) => ({\n ...f,\n content:\n !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n skipIfExists: f.skipIfExists ?? false,\n }));\n}\n\nexport function generateFiles(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n /** Scoped-generation signal (POST-MOUNT names); set on ctx for emitters to gate per-service emission. */\n scopedServices?: Set<string>;\n /** Canonical keys of services already on disk (prior manifest); narrows the scoped aggregate surface. */\n presentServiceKeys?: Set<string>;\n },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n const ctx = buildEmitterContext(spec, options);\n const files = generateAllFiles(spec, emitter, ctx);\n // Record operations for the SAME surface generateAllFiles emitted (scope ∪\n // already-on-disk in a scoped run; the full spec otherwise). Recording a\n // never-generated, out-of-scope service here would persist it into the merged\n // manifest and make the next scoped run treat it as present — re-opening the\n // orphan it was just kept out of.\n const surfaceSpec: ApiSpec = { ...spec, services: aggregateSurfaceServices(spec, ctx) };\n const operations = emitter.buildOperationsMap?.(surfaceSpec, ctx);\n const header = emitter.fileHeader();\n return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path. Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n fromFilePath: string,\n importModulePath: string,\n knownPaths: Set<string>,\n): string | undefined {\n // Strip quotes from module path key (tree-sitter keeps them)\n const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n // Skip non-relative imports (node_modules, bare specifiers)\n if (!cleaned.startsWith('.')) return undefined;\n\n const dir = path.dirname(fromFilePath);\n const resolved = path.normalize(path.join(dir, cleaned));\n\n // Try exact match, .ts, /index.ts\n for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n if (knownPaths.has(candidate)) return candidate;\n }\n return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target. Roots are entry points from which we trace\n * the import graph. Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n // Fixtures are never roots (and should be filtered by integrateTarget already)\n if (filePath.includes('/fixtures/')) return false;\n // Test files are roots — they are standalone entry points that belong in the\n // target repo even though nothing imports them.\n if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n // Serializer files\n if (filePath.includes('/serializers/')) return false;\n // Standalone interface files (not barrel/index)\n if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points. Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n if (!hasGrammar(language)) return files;\n\n const knownPaths = new Set(files.map((f) => f.path));\n\n // Build dependency graph: file → set of files it imports\n const deps = new Map<string, Set<string>>();\n for (const file of files) {\n // Only parse .ts/.js files (skip JSON, etc.)\n if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n deps.set(file.path, new Set());\n continue;\n }\n const parsed = await extractStatements(file.content, language);\n const fileDeps = new Set<string>();\n for (const imp of parsed.imports) {\n const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n // Also check re-export statements (export * from './foo')\n for (const stmt of parsed.statements) {\n if (stmt.kind === 'reexport') {\n // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n if (match) {\n const resolved = resolveImportPath(file.path, match[1], knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n }\n }\n deps.set(file.path, fileDeps);\n }\n\n // Determine which file extensions are source code for this language\n const codeExtensions = new Set([\n '.ts',\n '.js',\n '.tsx',\n '.jsx',\n '.py',\n '.rb',\n '.go',\n '.rs',\n '.kt',\n '.cs',\n '.ex',\n '.exs',\n '.php',\n ]);\n\n // BFS from roots\n const reachable = new Set<string>();\n const queue: string[] = [];\n for (const file of files) {\n const ext = file.path.slice(file.path.lastIndexOf('.'));\n // Non-code files (JSON, etc.) are always reachable — they can't participate\n // in the import graph and are loaded at runtime (e.g. test fixtures).\n if (!codeExtensions.has(ext)) {\n reachable.add(file.path);\n continue;\n }\n if (isRootFile(file.path)) {\n reachable.add(file.path);\n queue.push(file.path);\n }\n }\n while (queue.length > 0) {\n const current = queue.pop()!;\n const fileDeps = deps.get(current);\n if (!fileDeps) continue;\n for (const dep of fileDeps) {\n if (!reachable.has(dep)) {\n reachable.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n const langPrefix = `${language}/`;\n return files\n .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n .map((f) => {\n const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n return {\n ...f,\n skipIfExists: false, // Always merge in target — never hard-skip\n path: stripped,\n };\n });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`. This preserves backward-compatible imports\n * (e.g., `from acme.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n files: GeneratedFile[],\n targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n const result = [...files];\n const removals: string[] = [];\n\n for (let i = 0; i < result.length; i++) {\n const file = result[i];\n // Match package init files: e.g., src/acme/api_keys/__init__.py\n const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n if (!match) continue;\n\n const dirPath = match[1]; // e.g., src/acme/api_keys\n const moduleFilePath = `${dirPath}.py`; // e.g., src/acme/api_keys.py\n const fullModulePath = path.join(targetDir, moduleFilePath);\n\n let moduleContent: string;\n try {\n moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n } catch {\n continue; // Module file doesn't exist — no conflict\n }\n\n // Create a compat shim inside the package with the old module's content\n const compatPath = `${dirPath}/_compat.py`;\n result.push({\n path: compatPath,\n content: moduleContent,\n overwriteExisting: true,\n });\n\n // Append re-export from _compat to __init__.py so existing imports work.\n // Compat must come AFTER generated models so hand-written types take\n // precedence over generated types with the same name.\n const compatImport = 'from ._compat import * # noqa: F401,F403 # pyright: ignore[reportUnusedImport]';\n const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n result[i] = {\n ...file,\n content: existingContent + compatImport + '\\n',\n };\n\n // Schedule the shadowed module file for removal\n removals.push(fullModulePath);\n }\n\n return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n files: GeneratedFile[];\n language: string;\n targetDir: string;\n header: string;\n}): Promise<IntegrateResult> {\n const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n const shaken = await treeShakeFiles(mapped, opts.language);\n\n // Handle file-to-directory conflicts before writing\n const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n const result = await writeFiles(resolved, opts.targetDir, {\n language: opts.language,\n header: opts.header,\n });\n\n // Remove shadowed module files after integration\n for (const filePath of removals) {\n try {\n await fs.unlink(filePath);\n } catch {\n // File may already be gone\n }\n }\n\n // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n // Tree-shaking decides what to write, but shaken files are still oagen-managed\n // and must not be pruned from the target on subsequent runs.\n return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n if (!emitter.formatCommand) return;\n\n const formatCmd = emitter.formatCommand(targetDir);\n if (!formatCmd) return;\n\n const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n const batchSize = formatCmd.batchSize ?? 100;\n\n process.stderr.write(\n `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n );\n\n for (let i = 0; i < absolutePaths.length; i += batchSize) {\n const batch = absolutePaths.slice(i, i + batchSize);\n try {\n await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n cwd: targetDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 120_000,\n });\n } catch (err) {\n // Formatter failed on this batch — continue with remaining batches.\n // Surface the failure on stderr so misconfigured commands don't silently\n // leave generated code unformatted every regen.\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n }\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { canonicalServiceKey } from './scoped-services.js';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir). On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n * - The manifest is versioned so future format changes can be handled safely.\n * - Paths are stored sorted for deterministic diffs in git.\n * - Deletion is gated on a header guard when one is available: we only remove\n * files whose contents start with the auto-generated header. This protects\n * a hand-maintained file that happens to share a name with a previously\n * generated one (extremely rare, but worth catching).\n * - On first adoption (no previous manifest), pruning is skipped and a\n * one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n /** Schema version. Bump when the format changes incompatibly. */\n version: number;\n /** Emitter language (e.g. \"python\"). Used only as a consistency hint. */\n language: string;\n /** Human-readable or package-level SDK identity (e.g. \"acme-php\"). */\n sdkName?: string;\n /** ISO-8601 timestamp of the run that produced the current manifest contents. */\n generatedAt: string;\n /** SHA-256 hash of the source OpenAPI spec used for generation. */\n specSha?: string;\n /** Path or reference to the source spec. */\n specPath?: string;\n /** Git SHA or version of the emitter code used. */\n emitterSha?: string;\n /** Emitter version string if available. */\n emitterVersion?: string;\n /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n configSha?: string;\n /** Version of the compat snapshot/report schema expected by this generation. */\n compatSchemaVersion?: string;\n /** Sorted list of paths, relative to the manifest's containing directory. */\n files: string[];\n /** Maps \"METHOD /path\" to SDK method + service property name. */\n operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n /** Paths actually deleted. */\n pruned: string[];\n /** Paths skipped because the header guard didn't match (preserved). */\n preserved: string[];\n /** Paths already absent on disk (nothing to do). */\n missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory. Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<Manifest>;\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.language !== 'string' ||\n typeof parsed.generatedAt !== 'string' ||\n !Array.isArray(parsed.files) ||\n !parsed.files.every((p): p is string => typeof p === 'string')\n ) {\n return null;\n }\n if (parsed.version > MANIFEST_VERSION) {\n console.warn(\n `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n );\n return null;\n }\n // v1 manifests are forward-compatible — new fields are simply absent\n return parsed as Manifest;\n } catch {\n return null;\n }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n language: string;\n files: Iterable<string>;\n sdkName?: string;\n specSha?: string;\n specPath?: string;\n emitterSha?: string;\n emitterVersion?: string;\n configSha?: string;\n compatSchemaVersion?: string;\n operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n const manifest: Manifest = {\n version: MANIFEST_VERSION,\n language: opts.language,\n ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n generatedAt: new Date().toISOString(),\n ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n files: [...new Set(opts.files)].sort(),\n ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n };\n const previous = await readManifest(dir);\n if (previous && sameManifestExceptGeneratedAt(previous, manifest)) {\n manifest.generatedAt = previous.generatedAt;\n }\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\nfunction sameManifestExceptGeneratedAt(a: Manifest, b: Manifest): boolean {\n const { generatedAt: _aGeneratedAt, ...aComparable } = a;\n const { generatedAt: _bGeneratedAt, ...bComparable } = b;\n return JSON.stringify(aComparable) === JSON.stringify(bComparable);\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n const current = new Set(currentPaths);\n return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Merge a scoped run's emitted records into the prior manifest's records.\n *\n * A scoped (`--services`) run only emits files for the selected services, but it\n * must NOT discard the prior manifest's record of unselected services' files\n * records. The result unions prior + scoped file paths and shallow-merges the\n * operations maps, with scoped operations overriding prior entries for the same\n * \"METHOD /path\" key (a re-emission updates that operation's record).\n *\n * When `prev` is null (the first-ever run is scoped) there is nothing to\n * preserve, so the scoped subset is returned unchanged — matching the\n * first-adoption behavior of a full run.\n */\nexport function mergeScopedManifestRecords(\n prev: Manifest | null,\n scopedFiles: Iterable<string>,\n scopedOperations?: Record<string, unknown>,\n): { files: string[]; operations?: Record<string, unknown> } {\n const scopedFileList = [...scopedFiles];\n if (!prev) {\n return { files: scopedFileList, operations: scopedOperations };\n }\n const files = [...new Set([...prev.files, ...scopedFileList])].sort();\n const priorOps = prev.operations;\n const operations = priorOps || scopedOperations ? { ...priorOps, ...scopedOperations } : undefined;\n return { files, operations };\n}\n\n/**\n * Extract the set of services a prior manifest records as already generated on\n * disk, as canonical (casing/separator-insensitive) keys.\n *\n * The manifest's `operations` map carries each operation's owning `service`\n * (snake_case for most emitters, camelCase for Kotlin). A scoped (`--services`)\n * run uses this to tell \"service in the spec that is already on disk\" apart from\n * \"service the spec just added that this SDK has never generated\" — only the\n * former may be wired into aggregate/barrel/client files alongside the\n * selection, so a brand-new out-of-scope service is never referenced by files\n * whose implementation this run does not emit.\n *\n * Returns an empty set when the manifest is null or carries no operations\n * (a legacy manifest with no operations data); callers treat that as \"present\n * set unknown\" and fall back to not narrowing the surface.\n */\nexport function manifestServiceKeys(manifest: Manifest | null): Set<string> {\n const keys = new Set<string>();\n const ops = manifest?.operations;\n if (!ops) return keys;\n for (const value of Object.values(ops)) {\n const entries = Array.isArray(value) ? value : [value];\n for (const entry of entries) {\n const service = (entry as { service?: unknown } | null)?.service;\n if (typeof service === 'string' && service.length > 0) {\n keys.add(canonicalServiceKey(service));\n }\n }\n }\n return keys;\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered. When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting. Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n dir: string,\n paths: string[],\n opts: { header?: string } = {},\n): Promise<PruneResult> {\n const pruned: string[] = [];\n const preserved: string[] = [];\n const missing: string[] = [];\n\n for (const relPath of paths) {\n const fullPath = path.join(dir, relPath);\n let content: string;\n try {\n content = await fs.readFile(fullPath, 'utf-8');\n } catch {\n missing.push(relPath);\n continue;\n }\n if (opts.header && !content.startsWith(opts.header)) {\n preserved.push(relPath);\n continue;\n }\n try {\n await fs.unlink(fullPath);\n pruned.push(relPath);\n } catch {\n // Racing deletion or permission issue — treat as missing rather than fatal.\n missing.push(relPath);\n continue;\n }\n await removeEmptyParents(path.dirname(fullPath), dir);\n }\n\n return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory. Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n let current = path.resolve(startDir);\n const stop = path.resolve(stopDir);\n while (current.startsWith(stop + path.sep) && current !== stop) {\n let entries: string[];\n try {\n entries = await fs.readdir(current);\n } catch {\n return;\n }\n if (entries.length > 0) return;\n try {\n await fs.rmdir(current);\n } catch {\n return;\n }\n current = path.dirname(current);\n }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { resolveScopedServices } from './scoped-services.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport {\n computeStalePaths,\n manifestServiceKeys,\n MANIFEST_FILENAME,\n mergeScopedManifestRecords,\n pruneStaleFiles,\n readManifest,\n writeManifest,\n} from './manifest.js';\n\nexport async function generate(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n dryRun?: boolean;\n outputDir: string;\n target?: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n modelHints?: Record<string, string>;\n emitterOptions?: Record<string, unknown>;\n /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n noPrune?: boolean;\n /**\n * Post-mount service names to generate (a `--services` run). When non-empty,\n * the FULL spec is still emitted for models/enums/client/barrels (so shared\n * files stay byte-identical and a brand-new selected service is wired into the\n * client automatically); only per-service resource/test emission is gated to\n * the selection (via `ctx.scopedServices`). Pruning is disabled and the\n * manifest is merged so unselected services' records survive.\n */\n services?: string[];\n },\n): Promise<GeneratedFile[]> {\n // Scoped generation: validate + expand the selection to POST-MOUNT names. The\n // spec is NOT filtered — placement/dedup/shared-schemas are computed over the\n // full spec so shared files stay byte-identical; emitters gate only per-service\n // resource/test emission on this set.\n const scopedServices =\n options.services && options.services.length > 0\n ? resolveScopedServices(spec, options.services, options.mountRules)\n : undefined;\n const scoped = scopedServices !== undefined;\n // Scoped mode implies no-prune so unselected services' files survive.\n const noPrune = options.noPrune === true || scoped;\n\n // Read previous manifests up front so emitters can mark files the prior run\n // wrote as safe-to-overwrite (vs files a human hand-maintains), and so scoped\n // runs can merge prior records. Skipped only when --no-prune is set on a\n // non-scoped run (opting out of lifecycle tracking). Scoped runs always read,\n // even though they force no-prune, because the merge needs the prior records.\n const skipManifestRead = options.noPrune === true && !scoped;\n const outputPrevManifestForCtx = skipManifestRead ? null : await readManifest(options.outputDir);\n const targetManifestForCtx = options.target && !skipManifestRead ? await readManifest(options.target) : null;\n const priorManifestForCtx = targetManifestForCtx ?? outputPrevManifestForCtx;\n const priorTargetManifestPaths = priorManifestForCtx ? new Set(priorManifestForCtx.files) : undefined;\n // Services already generated on disk (from the prior manifest's operations).\n // Only consulted in a scoped run: it keeps already-present services in the\n // aggregate/barrel/client surface (byte-identical regen) while excluding a\n // service the spec just added that this SDK has never generated — which would\n // otherwise be wired into the client/barrels with no implementation behind it.\n const presentServiceKeys = scoped ? manifestServiceKeys(priorManifestForCtx) : undefined;\n\n const {\n files: withHeaders,\n header,\n operations,\n } = generateFiles(spec, emitter, {\n ...options,\n priorTargetManifestPaths,\n scopedServices,\n presentServiceKeys,\n });\n\n if (options.dryRun) {\n if (options.target) {\n console.log(`\\nTarget integration (${options.target}):`);\n for (const f of withHeaders) {\n console.log(` ${f.path}`);\n }\n }\n return withHeaders;\n }\n\n // Reuse the manifest read before generation; nothing above writes it.\n const outputPrevManifest = outputPrevManifestForCtx;\n\n const writeResult = await writeFiles(withHeaders, options.outputDir, {\n language: emitter.language,\n header,\n });\n\n if (writeResult.merged.length > 0) {\n console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n }\n if (writeResult.ignored.length > 0) {\n console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n }\n\n const outputEmittedPaths = withHeaders.map((f) => f.path);\n await applyManifestPrune({\n dir: options.outputDir,\n label: 'Output',\n prevManifest: outputPrevManifest,\n currentPaths: outputEmittedPaths,\n language: emitter.language,\n header,\n noPrune,\n operations,\n scoped,\n });\n\n // Format output files so the emitter's formatter runs even without --target.\n const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n if (allOutputFiles.length > 0) {\n await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n }\n\n // Target integration pass\n if (options.target) {\n // Reuse the manifest we already read to build the emitter context. This\n // is correct because nothing between the two reads writes the manifest.\n const targetPrevManifest = targetManifestForCtx;\n\n const targetResult = await integrateGeneratedFiles({\n files: withHeaders,\n language: emitter.language,\n targetDir: options.target,\n header,\n });\n\n if (targetResult.written.length > 0) {\n console.log(`Target: created ${targetResult.written.length} new files`);\n }\n if (targetResult.merged.length > 0) {\n console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n }\n if (targetResult.skipped.length > 0) {\n console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n }\n\n await applyManifestPrune({\n dir: options.target,\n label: 'Target',\n prevManifest: targetPrevManifest,\n currentPaths: targetResult.emittedPaths,\n language: emitter.language,\n header,\n noPrune,\n operations,\n scoped,\n });\n\n // Run the emitter's formatter on all written/merged/identical files\n const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n if (allTargetFiles.length > 0) {\n await formatTargetFiles(emitter, options.target, allTargetFiles);\n }\n }\n\n return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest. Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n dir: string;\n label: string;\n prevManifest: Awaited<ReturnType<typeof readManifest>>;\n currentPaths: string[];\n language: string;\n header: string;\n noPrune?: boolean;\n operations?: Record<string, unknown>;\n /** When true, union this scoped run's records with the prior manifest. */\n scoped?: boolean;\n}): Promise<void> {\n // A scoped run only emits the selected services' files, so the manifest is\n // merged with the prior records rather than replaced — otherwise unselected\n // services would be dropped from the manifest and mis-pruned on the next run.\n const records = opts.scoped\n ? mergeScopedManifestRecords(opts.prevManifest, opts.currentPaths, opts.operations)\n : { files: opts.currentPaths, operations: opts.operations };\n const manifestOpts = { language: opts.language, files: records.files, operations: records.operations };\n if (opts.noPrune) {\n // Still refresh the manifest so future runs with pruning enabled have a baseline.\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n if (!opts.prevManifest) {\n console.log(\n `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n );\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n if (stale.length > 0) {\n const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n if (pruned.length > 0) {\n console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n }\n if (preserved.length > 0) {\n console.log(\n `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n );\n for (const p of preserved) console.log(` ${p}`);\n }\n }\n\n await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n const emitter = emitters.get(language);\n if (!emitter) {\n const available = [...emitters.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `Unknown language: ${language}. Available: ${available}`,\n `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n );\n }\n return emitter;\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n switch (kind) {\n case 'field-added':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'field-removed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-type-changed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-format-changed':\n // A primitive's `format` changing (e.g., string → string format=email)\n // is classified additive at the IR level: the wire-format base type is\n // unchanged, so callers' deserialization keeps working. Per-emitter\n // compat checks catch any source-level break a specific language layers\n // on top (e.g., a typed Email value object in TypeScript).\n return { kind, fieldName, classification: 'additive' };\n case 'field-required-changed':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n details: isRequired ? 'optional → required' : 'required → optional',\n };\n case 'field-access-changed':\n return { kind, fieldName, classification: 'breaking' };\n }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n switch (kind) {\n case 'param-added':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-removed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-type-changed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-format-changed':\n // See `field-format-changed`: format-only diffs are additive at the IR\n // layer.\n return { kind, paramName, classification: 'additive' };\n case 'param-required-changed':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-default-changed':\n // Removing or changing a default that callers may have implicitly relied on\n // changes runtime behavior for clients who never set the param explicitly.\n // We treat this as breaking so it surfaces as a major bump rather than\n // sliding through as a silent regression.\n return { kind, paramName, classification: 'breaking' };\n }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'model-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newModel] of newByName) {\n const oldModel = oldByName.get(name);\n if (!oldModel) continue;\n\n const fieldChanges = diffFields(oldModel, newModel);\n if (fieldChanges.length > 0) {\n const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n changes.push({\n kind: 'model-modified',\n name,\n fieldChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n const changes: FieldChange[] = [];\n const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n for (const [name, field] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyFieldChange('field-added', name, field.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyFieldChange('field-removed', name));\n }\n }\n\n for (const [name, newField] of newByName) {\n const oldField = oldByName.get(name);\n if (!oldField) continue;\n\n if (!typeRefsEqual(oldField.type, newField.type)) {\n if (primitivesDifferOnlyByFormat(oldField.type, newField.type)) {\n changes.push({\n ...classifyFieldChange('field-format-changed', name),\n details: formatChangeDetails(oldField.type, newField.type),\n });\n } else {\n changes.push({\n kind: 'field-type-changed',\n fieldName: name,\n classification: 'breaking',\n details: `type changed`,\n });\n }\n }\n\n if (oldField.required !== newField.required) {\n changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n }\n\n if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n changes.push(classifyFieldChange('field-access-changed', name));\n }\n }\n\n return changes;\n}\n\n/**\n * True when both refs are primitives with the same base `type` but different\n * `format`. Used to downgrade format-only diffs from breaking type changes to\n * additive `field-format-changed` / `param-format-changed` events: the wire\n * base type is unchanged, so the diff is a hint to language emitters rather\n * than a source-level break.\n */\nexport function primitivesDifferOnlyByFormat(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== 'primitive' || b.kind !== 'primitive') return false;\n if (a.type !== b.type) return false;\n return (a.format ?? '') !== (b.format ?? '');\n}\n\nexport function formatChangeDetails(a: TypeRef, b: TypeRef): string {\n const oldFmt = a.kind === 'primitive' ? a.format : undefined;\n const newFmt = b.kind === 'primitive' ? b.format : undefined;\n return `format ${oldFmt ?? '<unset>'} → ${newFmt ?? '<unset>'}`;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== b.kind) return false;\n\n switch (a.kind) {\n case 'primitive':\n return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n case 'array':\n return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n case 'model':\n return b.kind === 'model' && a.name === b.name;\n case 'enum':\n return b.kind === 'enum' && a.name === b.name;\n case 'literal':\n return b.kind === 'literal' && a.value === b.value;\n case 'nullable':\n return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n case 'union': {\n if (b.kind !== 'union') return false;\n if (a.variants.length !== b.variants.length) return false;\n if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n // Compare discriminator\n if (!a.discriminator && !b.discriminator) return true;\n if (!a.discriminator || !b.discriminator) return false;\n if (a.discriminator.property !== b.discriminator.property) return false;\n const aKeys = Object.keys(a.discriminator.mapping).sort();\n const bKeys = Object.keys(b.discriminator.mapping).sort();\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n }\n case 'map':\n return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n }\n return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { formatChangeDetails, primitivesDifferOnlyByFormat, typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({\n kind: 'operation-added',\n serviceName,\n operationName: name,\n classification: 'additive',\n });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({\n kind: 'operation-removed',\n serviceName,\n operationName: name,\n classification: 'breaking',\n });\n }\n }\n\n for (const [name, newOp] of newByName) {\n const oldOp = oldByName.get(name);\n if (!oldOp) continue;\n\n const paramChanges = diffParams(oldOp, newOp);\n const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n const pathChanged = oldOp.path !== newOp.path;\n const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n const errorsChanged = errorsDiff !== 'none';\n\n const hasChanges =\n paramChanges.length > 0 ||\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedChanged ||\n injectIdempotencyKeyChanged ||\n errorsChanged;\n\n if (hasChanges) {\n // paginated: false→true is additive (SDK gains pagination helper)\n // paginated: true→false is breaking (SDK loses pagination helper)\n const paginatedBreaking = paginatedChanged && !newOp.pagination;\n // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n const errorsBreaking = errorsDiff === 'breaking';\n\n const hasBreaking =\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedBreaking ||\n injectIdempotencyKeyBreaking ||\n errorsBreaking ||\n paramChanges.some((pc) => pc.classification === 'breaking');\n changes.push({\n kind: 'operation-modified',\n serviceName,\n operationName: name,\n paramChanges,\n responseChanged,\n requestBodyChanged,\n httpMethodChanged,\n pathChanged,\n paginatedChanged,\n injectIdempotencyKeyChanged,\n errorsChanged,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n oldErrors: ErrorResponse[],\n newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n let hasAdditive = false;\n let hasBreaking = false;\n\n // New error codes added → additive (SDK gains new error classes)\n for (const code of newByCode.keys()) {\n if (!oldByCode.has(code)) hasAdditive = true;\n }\n\n // Old error codes removed → breaking (SDK loses error classes)\n for (const code of oldByCode.keys()) {\n if (!newByCode.has(code)) hasBreaking = true;\n }\n\n // Shared error codes with changed types → breaking\n for (const [code, newErr] of newByCode) {\n const oldErr = oldByCode.get(code);\n if (!oldErr) continue;\n if (!oldErr.type && !newErr.type) continue;\n if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n hasBreaking = true;\n }\n }\n\n if (hasBreaking) return 'breaking';\n if (hasAdditive) return 'additive';\n return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n const changes: ParamChange[] = [];\n const tagged = (loc: 'path' | 'query' | 'header', params: typeof oldOp.queryParams) =>\n params.map((p) => ({ p, loc }));\n const allOldParams = [\n ...tagged('path', oldOp.pathParams),\n ...tagged('query', oldOp.queryParams),\n ...tagged('header', oldOp.headerParams),\n ];\n const allNewParams = [\n ...tagged('path', newOp.pathParams),\n ...tagged('query', newOp.queryParams),\n ...tagged('header', newOp.headerParams),\n ];\n const oldByName = new Map(allOldParams.map((e) => [e.p.name, e]));\n const newByName = new Map(allNewParams.map((e) => [e.p.name, e]));\n\n for (const [name, entry] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyParamChange('param-added', name, entry.p.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyParamChange('param-removed', name));\n }\n }\n\n for (const [name, newEntry] of newByName) {\n const oldEntry = oldByName.get(name);\n if (!oldEntry) continue;\n\n if (!typeRefsEqual(oldEntry.p.type, newEntry.p.type)) {\n if (primitivesDifferOnlyByFormat(oldEntry.p.type, newEntry.p.type)) {\n const change = classifyParamChange('param-format-changed', name);\n change.details = formatChangeDetails(oldEntry.p.type, newEntry.p.type);\n changes.push(change);\n } else {\n changes.push(classifyParamChange('param-type-changed', name));\n }\n }\n\n if (oldEntry.p.required !== newEntry.p.required) {\n changes.push(classifyParamChange('param-required-changed', name, newEntry.p.required));\n }\n\n const oldDefault = serializeDefault(oldEntry.p.default);\n const newDefault = serializeDefault(newEntry.p.default);\n if (oldDefault !== newDefault) {\n const change = classifyParamChange('param-default-changed', name);\n change.oldDefault = oldDefault;\n change.newDefault = newDefault;\n change.paramLocation = newEntry.loc;\n change.details = `default ${oldDefault ?? '<unset>'} → ${newDefault ?? '<unset>'}`;\n changes.push(change);\n }\n }\n\n return changes;\n}\n\nfunction serializeDefault(value: unknown): string | null {\n if (value === undefined) return null;\n if (value === null) return 'null';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n // Objects/arrays: stable JSON. Stringification of equal-valued objects is\n // deterministic enough for this comparison since callers typically pass\n // primitives; complex defaults are rare.\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'service-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newService] of newByName) {\n const oldService = oldByName.get(name);\n if (!oldService) continue;\n\n changes.push(...diffOperations(name, oldService.operations, newService.operations));\n }\n\n return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { BehaviorChange, Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n const changes: Change[] = [\n ...diffModels(oldSpec.models, newSpec.models),\n ...diffEnums(oldSpec.enums, newSpec.enums),\n ...diffServices(oldSpec.services, newSpec.services),\n ];\n\n const behaviorChanges = collectBehaviorChanges(changes);\n\n return {\n oldVersion: oldSpec.version,\n newVersion: newSpec.version,\n changes,\n behaviorChanges,\n summary: { ...summarize(changes), behaviorChanges: behaviorChanges.length },\n };\n}\n\nfunction collectBehaviorChanges(changes: Change[]): BehaviorChange[] {\n const out: BehaviorChange[] = [];\n for (const c of changes) {\n if (c.kind !== 'operation-modified') continue;\n for (const pc of c.paramChanges) {\n if (pc.kind !== 'param-default-changed') continue;\n out.push({\n kind: 'param-default-changed',\n serviceName: c.serviceName,\n operationName: c.operationName,\n paramName: pc.paramName,\n paramLocation: pc.paramLocation ?? 'query',\n oldDefault: pc.oldDefault ?? null,\n newDefault: pc.newDefault ?? null,\n classification: 'breaking',\n });\n }\n }\n return out;\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'enum-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newEnum] of newByName) {\n const oldEnum = oldByName.get(name);\n if (!oldEnum) continue;\n\n const valueChanges = diffEnumValues(oldEnum, newEnum);\n if (valueChanges.length > 0) {\n const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n changes.push({\n kind: 'enum-modified',\n name,\n valueChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n const changes: EnumValueChange[] = [];\n const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n }\n }\n\n for (const [name, newVal] of newByName) {\n const oldVal = oldByName.get(name);\n if (!oldVal) continue;\n\n if (oldVal.value !== newVal.value) {\n changes.push({\n kind: 'value-changed',\n valueName: name,\n classification: 'breaking',\n details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n });\n }\n }\n\n return changes;\n}\n\nfunction summarize(changes: Change[]) {\n let added = 0;\n let removed = 0;\n let modified = 0;\n let breaking = 0;\n let additive = 0;\n\n for (const c of changes) {\n if (c.kind.endsWith('-added')) added++;\n else if (c.kind.endsWith('-removed')) removed++;\n else if (c.kind.endsWith('-modified')) modified++;\n\n if (c.classification === 'breaking') breaking++;\n else additive++;\n }\n\n return { added, removed, modified, breaking, additive };\n}\n"],"mappings":"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"}