Fix bugs in diff hunk highlighting (#18454)
Fixes https://github.com/zed-industries/zed/issues/18405 In https://github.com/zed-industries/zed/pull/18313, we introduced a problem where git addition highlights might spuriously return when undoing certain changes. It turned out, there were already some cases where git hunk highlighting was incorrect when editing at the boundaries of expanded diff hunks. In this PR, I've introduced a test helper method for more rigorously (and readably) testing the editor's git state. You can assert about the entire state of an editor's diff decorations using a formatted diff: ```rust cx.assert_diff_hunks( r#" - use some::mod1; use some::mod2; const A: u32 = 42; - const B: u32 = 42; const C: u32 = 42; fn main() { - println!("hello"); + //println!("hello"); println!("world"); + // + // } fn another() { println!("another"); + println!("another"); } - fn another2() { println!("another2"); } "# .unindent(), ); ``` This will assert about the editor's actual row highlights, not just the editor's internal hunk-tracking state. I rewrote all of our editor diff tests to use these more high-level assertions, and it caught the new bug, as well as some pre-existing bugs in the highlighting of added content. The problem was how we *remove* highlighted rows. Previously, it relied on supplying exactly the same range as one that we had previously highlighted. I've added a `remove_highlighted_rows(ranges)` APIs which is much simpler - it clears out any row ranges that intersect the given ranges (which is all that we need for the Git diff use case). Release Notes: - N/A
This commit is contained in:
parent
caaa9a00a9
commit
c3075dfe9a
10 changed files with 654 additions and 1380 deletions
|
@ -88,116 +88,3 @@ pub(crate) fn build_editor_with_project(
|
|||
) -> Editor {
|
||||
Editor::new(EditorMode::Full, buffer, Some(project), true, cx)
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn editor_hunks(
|
||||
editor: &Editor,
|
||||
snapshot: &DisplaySnapshot,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Vec<(
|
||||
String,
|
||||
git::diff::DiffHunkStatus,
|
||||
std::ops::Range<crate::DisplayRow>,
|
||||
)> {
|
||||
use multi_buffer::MultiBufferRow;
|
||||
use text::Point;
|
||||
|
||||
use crate::hunk_status;
|
||||
|
||||
snapshot
|
||||
.buffer_snapshot
|
||||
.git_diff_hunks_in_range(MultiBufferRow::MIN..MultiBufferRow::MAX)
|
||||
.map(|hunk| {
|
||||
let display_range = Point::new(hunk.row_range.start.0, 0)
|
||||
.to_display_point(snapshot)
|
||||
.row()
|
||||
..Point::new(hunk.row_range.end.0, 0)
|
||||
.to_display_point(snapshot)
|
||||
.row();
|
||||
let (_, buffer, _) = editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.excerpt_containing(Point::new(hunk.row_range.start.0, 0), cx)
|
||||
.expect("no excerpt for expanded buffer's hunk start");
|
||||
let diff_base = buffer
|
||||
.read(cx)
|
||||
.diff_base()
|
||||
.expect("should have a diff base for expanded hunk")
|
||||
.slice(hunk.diff_base_byte_range.clone())
|
||||
.to_string();
|
||||
(diff_base, hunk_status(&hunk), display_range)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn expanded_hunks(
|
||||
editor: &Editor,
|
||||
snapshot: &DisplaySnapshot,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Vec<(
|
||||
String,
|
||||
git::diff::DiffHunkStatus,
|
||||
std::ops::Range<crate::DisplayRow>,
|
||||
)> {
|
||||
editor
|
||||
.expanded_hunks
|
||||
.hunks(false)
|
||||
.map(|expanded_hunk| {
|
||||
let hunk_display_range = expanded_hunk
|
||||
.hunk_range
|
||||
.start
|
||||
.to_display_point(snapshot)
|
||||
.row()
|
||||
..expanded_hunk
|
||||
.hunk_range
|
||||
.end
|
||||
.to_display_point(snapshot)
|
||||
.row();
|
||||
let (_, buffer, _) = editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.excerpt_containing(expanded_hunk.hunk_range.start, cx)
|
||||
.expect("no excerpt for expanded buffer's hunk start");
|
||||
let diff_base = buffer
|
||||
.read(cx)
|
||||
.diff_base()
|
||||
.expect("should have a diff base for expanded hunk")
|
||||
.slice(expanded_hunk.diff_base_byte_range.clone())
|
||||
.to_string();
|
||||
(diff_base, expanded_hunk.status, hunk_display_range)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn expanded_hunks_background_highlights(
|
||||
editor: &mut Editor,
|
||||
cx: &mut gpui::WindowContext,
|
||||
) -> Vec<std::ops::RangeInclusive<crate::DisplayRow>> {
|
||||
use crate::DisplayRow;
|
||||
|
||||
let mut highlights = Vec::new();
|
||||
|
||||
let mut range_start = 0;
|
||||
let mut previous_highlighted_row = None;
|
||||
for (highlighted_row, _) in editor.highlighted_display_rows(cx) {
|
||||
match previous_highlighted_row {
|
||||
Some(previous_row) => {
|
||||
if previous_row + 1 != highlighted_row.0 {
|
||||
highlights.push(DisplayRow(range_start)..=DisplayRow(previous_row));
|
||||
range_start = highlighted_row.0;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
range_start = highlighted_row.0;
|
||||
}
|
||||
}
|
||||
previous_highlighted_row = Some(highlighted_row.0);
|
||||
}
|
||||
if let Some(previous_row) = previous_highlighted_row {
|
||||
highlights.push(DisplayRow(range_start)..=DisplayRow(previous_row));
|
||||
}
|
||||
|
||||
highlights
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue