(
originalLines: string[],
filePath: string,
chunks: UpdateFileChunk[],
)
| 333 | } |
| 334 | |
| 335 | function computeReplacements( |
| 336 | originalLines: string[], |
| 337 | filePath: string, |
| 338 | chunks: UpdateFileChunk[], |
| 339 | ): Array<[number, number, string[]]> { |
| 340 | const replacements: Array<[number, number, string[]]> = [] |
| 341 | let lineIndex = 0 |
| 342 | |
| 343 | for (const chunk of chunks) { |
| 344 | // Handle context-based seeking |
| 345 | if (chunk.change_context) { |
| 346 | const contextIdx = seekSequence(originalLines, [chunk.change_context], lineIndex) |
| 347 | if (contextIdx === -1) { |
| 348 | throw new Error(`Failed to find context '${chunk.change_context}' in ${filePath}`) |
| 349 | } |
| 350 | lineIndex = contextIdx + 1 |
| 351 | } |
| 352 | |
| 353 | // Handle pure addition (no old lines) |
| 354 | if (chunk.old_lines.length === 0) { |
| 355 | const insertionIdx = |
| 356 | originalLines.length > 0 && originalLines[originalLines.length - 1] === "" |
| 357 | ? originalLines.length - 1 |
| 358 | : originalLines.length |
| 359 | replacements.push([insertionIdx, 0, chunk.new_lines]) |
| 360 | continue |
| 361 | } |
| 362 | |
| 363 | // Try to match old lines in the file |
| 364 | let pattern = chunk.old_lines |
| 365 | let newSlice = chunk.new_lines |
| 366 | let found = seekSequence(originalLines, pattern, lineIndex) |
| 367 | |
| 368 | // Retry without trailing empty line if not found |
| 369 | if (found === -1 && pattern.length > 0 && pattern[pattern.length - 1] === "") { |
| 370 | pattern = pattern.slice(0, -1) |
| 371 | if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "") { |
| 372 | newSlice = newSlice.slice(0, -1) |
| 373 | } |
| 374 | found = seekSequence(originalLines, pattern, lineIndex) |
| 375 | } |
| 376 | |
| 377 | if (found !== -1) { |
| 378 | replacements.push([found, pattern.length, newSlice]) |
| 379 | lineIndex = found + pattern.length |
| 380 | } else { |
| 381 | throw new Error(`Failed to find expected lines in ${filePath}:\n${chunk.old_lines.join("\n")}`) |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | // Sort replacements by index to apply in order |
| 386 | replacements.sort((a, b) => a[0] - b[0]) |
| 387 | |
| 388 | return replacements |
| 389 | } |
| 390 | |
| 391 | function applyReplacements(lines: string[], replacements: Array<[number, number, string[]]>): string[] { |
| 392 | // Apply replacements in reverse order to avoid index shifting |
no test coverage detected