diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 5909900b0e5e403769b76b6f0754905210d09c58..f5abdfa21978b4e13dbebc6bc8cfd2aade5837c9 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -664,11 +664,23 @@ impl BlockMap { .map(|(_, range)| range.end) .unwrap_or(wrap_snapshot.buffer_snapshot().max_point()); - let my_start = wrap_snapshot.make_wrap_point(my_start, Bias::Left); + let mut my_start = wrap_snapshot.make_wrap_point(my_start, Bias::Left); let mut my_end = wrap_snapshot.make_wrap_point(my_end, Bias::Left); if my_end.column() > 0 { - my_end.0.row += 1; - my_end.0.column = 0; + *my_end.row_mut() += 1; + *my_end.column_mut() = 0; + } + + // Empty edits won't survive Patch::compose, but we still need to make sure + // we recompute spacers when we get them. + if my_start.row() == my_end.row() { + if my_end.row() <= wrap_snapshot.max_point().row() { + *my_end.row_mut() += 1; + *my_end.column_mut() = 0; + } else if my_start.row() > WrapRow(0) { + *my_start.row_mut() += 1; + *my_start.column_mut() = 0; + } } WrapEdit { diff --git a/crates/editor/src/split.rs b/crates/editor/src/split.rs index d030c65e1b6ae08a6cbbcee4c5cc849d0510146a..e449b79c64c2a94b7e4cf332ff9bd99e0460a0e3 100644 --- a/crates/editor/src/split.rs +++ b/crates/editor/src/split.rs @@ -3355,4 +3355,98 @@ mod tests { &mut cx, ); } + + #[gpui::test] + async fn test_adding_line_to_addition_hunk(cx: &mut gpui::TestAppContext) { + use rope::Point; + use unindent::Unindent as _; + + let (editor, mut cx) = init_test(cx).await; + + let base_text = " + aaa + bbb + ccc + " + .unindent(); + + let current_text = " + aaa + bbb + xxx + yyy + ccc + " + .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( + &editor, + " + § + § ----- + aaa + bbb + xxx + yyy + ccc" + .unindent(), + " + § + § ----- + aaa + bbb + § spacer + § spacer + ccc" + .unindent(), + &mut cx, + ); + + buffer.update(cx, |buffer, cx| { + buffer.edit([(Point::new(3, 3)..Point::new(3, 3), "\nzzz")], None, cx); + }); + + cx.run_until_parked(); + + assert_split_content( + &editor, + " + § + § ----- + aaa + bbb + xxx + yyy + zzz + ccc" + .unindent(), + " + § + § ----- + aaa + bbb + § spacer + § spacer + § spacer + ccc" + .unindent(), + &mut cx, + ); + } }