Fix bugs in expanding diff hunk (#18885)
Release Notes: - Fixed an issue where diff hunks at the boundaries of multi buffer excerpts could not be expanded
This commit is contained in:
parent
b0a9005163
commit
e351148152
3 changed files with 85 additions and 54 deletions
|
@ -11715,6 +11715,60 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_expand_diff_hunk_at_excerpt_boundary(cx: &mut gpui::TestAppContext) {
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
|
let base = "aaa\nbbb\nccc\nddd\neee\nfff\nggg\n";
|
||||||
|
let text = "aaa\nBBB\nBB2\nccc\nDDD\nEEE\nfff\nggg\n";
|
||||||
|
|
||||||
|
let buffer = cx.new_model(|cx| {
|
||||||
|
let mut buffer = Buffer::local(text.to_string(), cx);
|
||||||
|
buffer.set_diff_base(Some(base.into()), cx);
|
||||||
|
buffer
|
||||||
|
});
|
||||||
|
|
||||||
|
let multi_buffer = cx.new_model(|cx| {
|
||||||
|
let mut multibuffer = MultiBuffer::new(ReadWrite);
|
||||||
|
multibuffer.push_excerpts(
|
||||||
|
buffer.clone(),
|
||||||
|
[
|
||||||
|
ExcerptRange {
|
||||||
|
context: Point::new(0, 0)..Point::new(2, 0),
|
||||||
|
primary: None,
|
||||||
|
},
|
||||||
|
ExcerptRange {
|
||||||
|
context: Point::new(5, 0)..Point::new(7, 0),
|
||||||
|
primary: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
multibuffer
|
||||||
|
});
|
||||||
|
|
||||||
|
let editor = cx.add_window(|cx| Editor::new(EditorMode::Full, multi_buffer, None, true, cx));
|
||||||
|
let mut cx = EditorTestContext::for_editor(editor, cx).await;
|
||||||
|
cx.run_until_parked();
|
||||||
|
|
||||||
|
cx.update_editor(|editor, cx| editor.expand_all_hunk_diffs(&Default::default(), cx));
|
||||||
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
|
cx.assert_diff_hunks(
|
||||||
|
"
|
||||||
|
aaa
|
||||||
|
- bbb
|
||||||
|
+ BBB
|
||||||
|
|
||||||
|
- ddd
|
||||||
|
- eee
|
||||||
|
+ EEE
|
||||||
|
fff
|
||||||
|
"
|
||||||
|
.unindent(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_edits_around_expanded_insertion_hunks(
|
async fn test_edits_around_expanded_insertion_hunks(
|
||||||
executor: BackgroundExecutor,
|
executor: BackgroundExecutor,
|
||||||
|
|
|
@ -209,19 +209,20 @@ impl Editor {
|
||||||
|
|
||||||
retain
|
retain
|
||||||
});
|
});
|
||||||
for remaining_hunk in hunks_to_toggle {
|
for hunk in hunks_to_toggle {
|
||||||
let remaining_hunk_point_range =
|
let remaining_hunk_point_range = Point::new(hunk.row_range.start.0, 0)
|
||||||
Point::new(remaining_hunk.row_range.start.0, 0)
|
..Point::new(hunk.row_range.end.0, 0);
|
||||||
..Point::new(remaining_hunk.row_range.end.0, 0);
|
let hunk_start = snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.anchor_before(remaining_hunk_point_range.start);
|
||||||
|
let hunk_end = snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.anchor_in_excerpt(hunk_start.excerpt_id, hunk.buffer_range.end)
|
||||||
|
.unwrap();
|
||||||
hunks_to_expand.push(HoveredHunk {
|
hunks_to_expand.push(HoveredHunk {
|
||||||
status: hunk_status(&remaining_hunk),
|
status: hunk_status(&hunk),
|
||||||
multi_buffer_range: snapshot
|
multi_buffer_range: hunk_start..hunk_end,
|
||||||
.buffer_snapshot
|
diff_base_byte_range: hunk.diff_base_byte_range.clone(),
|
||||||
.anchor_before(remaining_hunk_point_range.start)
|
|
||||||
..snapshot
|
|
||||||
.buffer_snapshot
|
|
||||||
.anchor_after(remaining_hunk_point_range.end),
|
|
||||||
diff_base_byte_range: remaining_hunk.diff_base_byte_range.clone(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,33 +247,22 @@ impl Editor {
|
||||||
hunk: &HoveredHunk,
|
hunk: &HoveredHunk,
|
||||||
cx: &mut ViewContext<'_, Editor>,
|
cx: &mut ViewContext<'_, Editor>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let multi_buffer_snapshot = self.buffer().read(cx).snapshot(cx);
|
let buffer = self.buffer.clone();
|
||||||
|
let multi_buffer_snapshot = buffer.read(cx).snapshot(cx);
|
||||||
let hunk_range = hunk.multi_buffer_range.clone();
|
let hunk_range = hunk.multi_buffer_range.clone();
|
||||||
let hunk_point_range = hunk_range.to_point(&multi_buffer_snapshot);
|
|
||||||
|
|
||||||
let buffer = self.buffer().clone();
|
|
||||||
let snapshot = self.snapshot(cx);
|
|
||||||
let (diff_base_buffer, deleted_text_lines) = buffer.update(cx, |buffer, cx| {
|
let (diff_base_buffer, deleted_text_lines) = buffer.update(cx, |buffer, cx| {
|
||||||
let hunk = buffer_diff_hunk(&snapshot.buffer_snapshot, hunk_point_range.clone())?;
|
let buffer = buffer.buffer(hunk_range.start.buffer_id?)?;
|
||||||
let mut buffer_ranges = buffer.range_to_buffer_ranges(hunk_point_range, cx);
|
let diff_base_buffer = diff_base_buffer
|
||||||
if buffer_ranges.len() == 1 {
|
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
||||||
let (buffer, _, _) = buffer_ranges.pop()?;
|
.or_else(|| create_diff_base_buffer(&buffer, cx))?;
|
||||||
let diff_base_buffer = diff_base_buffer
|
let deleted_text_lines = buffer.read(cx).diff_base().map(|diff_base| {
|
||||||
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
let diff_start_row = diff_base
|
||||||
.or_else(|| create_diff_base_buffer(&buffer, cx))?;
|
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||||
let buffer = buffer.read(cx);
|
.row;
|
||||||
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
let diff_end_row = diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
||||||
let diff_start_row = diff_base
|
diff_end_row - diff_start_row
|
||||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
})?;
|
||||||
.row;
|
Some((diff_base_buffer, deleted_text_lines))
|
||||||
let diff_end_row = diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
|
||||||
|
|
||||||
diff_end_row - diff_start_row
|
|
||||||
})?;
|
|
||||||
Some((diff_base_buffer, deleted_text_lines))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let block_insert_index = match self.expanded_hunks.hunks.binary_search_by(|probe| {
|
let block_insert_index = match self.expanded_hunks.hunks.binary_search_by(|probe| {
|
||||||
|
@ -1128,21 +1118,6 @@ fn editor_with_deleted_text(
|
||||||
(editor_height, editor)
|
(editor_height, editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_diff_hunk(
|
|
||||||
buffer_snapshot: &MultiBufferSnapshot,
|
|
||||||
row_range: Range<Point>,
|
|
||||||
) -> Option<MultiBufferDiffHunk> {
|
|
||||||
let mut hunks = buffer_snapshot.git_diff_hunks_in_range(
|
|
||||||
MultiBufferRow(row_range.start.row)..MultiBufferRow(row_range.end.row),
|
|
||||||
);
|
|
||||||
let hunk = hunks.next()?;
|
|
||||||
let second_hunk = hunks.next();
|
|
||||||
if second_hunk.is_none() {
|
|
||||||
return Some(hunk);
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DisplayDiffHunk {
|
impl DisplayDiffHunk {
|
||||||
pub fn start_display_row(&self) -> DisplayRow {
|
pub fn start_display_row(&self) -> DisplayRow {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1209,7 +1184,10 @@ pub fn diff_hunk_to_display(
|
||||||
let hunk_end_point = Point::new(hunk_end_row.0, 0);
|
let hunk_end_point = Point::new(hunk_end_row.0, 0);
|
||||||
|
|
||||||
let multi_buffer_start = snapshot.buffer_snapshot.anchor_before(hunk_start_point);
|
let multi_buffer_start = snapshot.buffer_snapshot.anchor_before(hunk_start_point);
|
||||||
let multi_buffer_end = snapshot.buffer_snapshot.anchor_after(hunk_end_point);
|
let multi_buffer_end = snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.anchor_in_excerpt(multi_buffer_start.excerpt_id, hunk.buffer_range.end)
|
||||||
|
.unwrap();
|
||||||
let end = hunk_end_point.to_display_point(snapshot).row();
|
let end = hunk_end_point.to_display_point(snapshot).row();
|
||||||
|
|
||||||
DisplayDiffHunk::Unfolded {
|
DisplayDiffHunk::Unfolded {
|
||||||
|
|
|
@ -1156,7 +1156,6 @@ impl Buffer {
|
||||||
this.non_text_state_update_count += 1;
|
this.non_text_state_update_count += 1;
|
||||||
if let Some(BufferDiffBase::PastBufferVersion { rope, .. }) = &mut this.diff_base {
|
if let Some(BufferDiffBase::PastBufferVersion { rope, .. }) = &mut this.diff_base {
|
||||||
*rope = diff_base_rope;
|
*rope = diff_base_rope;
|
||||||
cx.emit(BufferEvent::DiffBaseChanged);
|
|
||||||
}
|
}
|
||||||
cx.emit(BufferEvent::DiffUpdated);
|
cx.emit(BufferEvent::DiffUpdated);
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue