From bc7c7953fc3f77685996308ee365a7441fa3513f Mon Sep 17 00:00:00 2001 From: Amadeus Demarzi Date: Thu, 26 Mar 2026 11:44:39 -0700 Subject: [PATCH] Fix diffAcceptRejectHunk with partial FileDiffMetadata --- packages/diffs/src/utils/resolveRegion.ts | 51 +++++++++++++++---- .../diffs/test/diffAcceptRejectHunk.test.ts | 50 ++++++++++++++++++ 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/packages/diffs/src/utils/resolveRegion.ts b/packages/diffs/src/utils/resolveRegion.ts index e3b9b8c77..3b9783c0e 100644 --- a/packages/diffs/src/utils/resolveRegion.ts +++ b/packages/diffs/src/utils/resolveRegion.ts @@ -74,22 +74,18 @@ export function resolveRegion( const updatesEOFState = hunkIndex === hunks.length - 1 && endContentIndex === currentHunk.hunkContent.length - 1; + const shouldProcessCollapsedContext = !diff.isPartial; for (const [index, hunk] of hunks.entries()) { - pushCollapsedContextLines( + processCollapsedContext( + diff, resolvedDiff, - deletionLines, - additionLines, + cursor, hunk.deletionLineIndex - hunk.collapsedBefore, hunk.additionLineIndex - hunk.collapsedBefore, - hunk.collapsedBefore + hunk.collapsedBefore, + shouldProcessCollapsedContext ); - cursor.nextAdditionLineIndex += hunk.collapsedBefore; - cursor.nextDeletionLineIndex += hunk.collapsedBefore; - cursor.nextAdditionStart += hunk.collapsedBefore; - cursor.nextDeletionStart += hunk.collapsedBefore; - cursor.splitLineCount += hunk.collapsedBefore; - cursor.unifiedLineCount += hunk.collapsedBefore; const newHunk: Hunk = { ...hunk, @@ -236,6 +232,41 @@ function pushCollapsedContextLines( } } +// Partial patches track omitted context in `collapsedBefore`, but those lines do +// not exist in the diff's line arrays. Keep the virtual row counts and file +// positions in sync without inventing hidden lines. +function processCollapsedContext( + sourceDiff: FileDiffMetadata, + resolvedDiff: FileDiffMetadata, + cursor: CursorState, + deletionLineIndex: number, + additionLineIndex: number, + lineCount: number, + shouldProcessContent: boolean +) { + if (lineCount <= 0) { + return; + } + + if (shouldProcessContent) { + pushCollapsedContextLines( + resolvedDiff, + sourceDiff.deletionLines, + sourceDiff.additionLines, + deletionLineIndex, + additionLineIndex, + lineCount + ); + cursor.nextAdditionLineIndex += lineCount; + cursor.nextDeletionLineIndex += lineCount; + } + + cursor.nextAdditionStart += lineCount; + cursor.nextDeletionStart += lineCount; + cursor.splitLineCount += lineCount; + cursor.unifiedLineCount += lineCount; +} + function pushContentLinesToDiff( content: ContextContent | ChangeContent, diff: FileDiffMetadata, diff --git a/packages/diffs/test/diffAcceptRejectHunk.test.ts b/packages/diffs/test/diffAcceptRejectHunk.test.ts index 6732b9b0a..20692036f 100644 --- a/packages/diffs/test/diffAcceptRejectHunk.test.ts +++ b/packages/diffs/test/diffAcceptRejectHunk.test.ts @@ -8,6 +8,7 @@ import type { import { diffAcceptRejectHunk } from '../src/utils/diffAcceptRejectHunk'; import { parseDiffFromFile } from '../src/utils/parseDiffFromFile'; import { parseMergeConflictDiffFromFile } from '../src/utils/parseMergeConflictDiffFromFile'; +import { parsePatchFiles } from '../src/utils/parsePatchFiles'; import { resolveConflict } from '../src/utils/resolveConflict'; import { verifyFileDiffHunkValues } from './testUtils'; @@ -83,6 +84,32 @@ function createFixture() { ); } +function createPartialFixture() { + const patch = `diff --git a/index.html b/index.html +index 36c553c..711c67c 100644 +--- a/index.html ++++ b/index.html +@@ -6,8 +6,9 @@ + + +
+-

Welcome

+-

Thanks for visiting

++

Welcome to Our Site

++

We're glad you're here

++ Learn More +
+