From 35160555da6478945420a45d5ed6482cb9750f70 Mon Sep 17 00:00:00 2001 From: Cole Miller Date: Sat, 7 Feb 2026 13:07:23 -0500 Subject: [PATCH] git: Fix a potential misalignment in the side-by-side diff (#48690) Release Notes: - N/A --- crates/editor/src/display_map/block_map.rs | 24 ++-- crates/editor/src/split.rs | 130 +++++++++++++++++++++ 2 files changed, 146 insertions(+), 8 deletions(-) diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index e9411f653398dab97e3264fd15039064f660f566..3489c8774811a2201b0e0ad526b867fb68df7b44 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -1337,14 +1337,22 @@ impl BlockMap { break; } - let (delta_at_end, spacer_at_end) = determine_spacer( - &mut our_wrapper, - &mut companion_wrapper, - current_boundary, - current_range.end, - delta, - ); - delta = delta_at_end; + let edit_for_current_boundary = + excerpt.patch.edit_for_old_position(current_boundary); + + let spacer_at_end = if current_boundary == edit_for_current_boundary.old.end { + let (delta_at_end, spacer_at_end) = determine_spacer( + &mut our_wrapper, + &mut companion_wrapper, + current_boundary, + current_range.end, + delta, + ); + delta = delta_at_end; + spacer_at_end + } else { + None + }; if let Some((wrap_row, mut height)) = spacer_at_start { if let Some((_, additional_height)) = spacer_at_end { diff --git a/crates/editor/src/split.rs b/crates/editor/src/split.rs index 7d5a4ef15b8a52eadff21c56bfb0bcfdcbdc9614..d14cc34d4ed646dbc68fb35d64ad27515abd53b8 100644 --- a/crates/editor/src/split.rs +++ b/crates/editor/src/split.rs @@ -3945,6 +3945,136 @@ mod tests { assert_eq!( lhs_pos.x, rhs_pos.x, "LHS should have same horizontal scroll position as RHS after autoscroll" + ) + } + + #[gpui::test] + async fn test_edit_line_before_soft_wrapped_line_preceding_hunk(cx: &mut gpui::TestAppContext) { + use rope::Point; + use unindent::Unindent as _; + + let (editor, mut cx) = init_test(cx, SoftWrap::EditorWidth).await; + + let base_text = " + first line + aaaa bbbb cccc dddd eeee ffff + original + " + .unindent(); + + let current_text = " + first line + aaaa bbbb cccc dddd eeee ffff + modified + " + .unindent(); + + let (buffer, diff) = buffer_with_diff(&base_text, ¤t_text, &mut cx); + + editor.update(cx, |editor, cx| { + let path = PathKey::for_buffer(&buffer, cx); + editor.set_excerpts_for_path( + path, + buffer.clone(), + vec![Point::new(0, 0)..buffer.read(cx).max_point()], + 0, + diff.clone(), + cx, + ); + }); + + cx.run_until_parked(); + + assert_split_content_with_widths( + &editor, + px(400.0), + px(200.0), + " + § + § ----- + first line + aaaa bbbb cccc dddd eeee ffff + § spacer + § spacer + modified" + .unindent(), + " + § + § ----- + first line + aaaa bbbb\x20 + cccc dddd\x20 + eeee ffff + original" + .unindent(), + &mut cx, + ); + + buffer.update(cx, |buffer, cx| { + buffer.edit( + [(Point::new(0, 0)..Point::new(0, 10), "edited first")], + None, + cx, + ); + }); + + cx.run_until_parked(); + + assert_split_content_with_widths( + &editor, + px(400.0), + px(200.0), + " + § + § ----- + edited first + aaaa bbbb cccc dddd eeee ffff + § spacer + § spacer + modified" + .unindent(), + " + § + § ----- + first line + aaaa bbbb\x20 + cccc dddd\x20 + eeee ffff + original" + .unindent(), + &mut cx, + ); + + let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.text_snapshot()); + diff.update(cx, |diff, cx| { + diff.recalculate_diff_sync(&buffer_snapshot, cx); + }); + + cx.run_until_parked(); + + assert_split_content_with_widths( + &editor, + px(400.0), + px(200.0), + " + § + § ----- + edited first + aaaa bbbb cccc dddd eeee ffff + § spacer + § spacer + modified" + .unindent(), + " + § + § ----- + first line + aaaa bbbb\x20 + cccc dddd\x20 + eeee ffff + original" + .unindent(), + &mut cx, ); }