Properly calculate expanded git diff hunk highlight ranges (#11632)

Closes https://github.com/zed-industries/zed/issues/11576

Release Notes:

- Fixed expanded diff hunks highlighting an extra row as added
([11576](https://github.com/zed-industries/zed/issues/11576))
This commit is contained in:
Kirill Bulatov 2024-05-10 02:02:56 +03:00 committed by GitHub
parent 50c45c7897
commit 4762e52d31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 161 additions and 121 deletions

View File

@ -2110,10 +2110,7 @@ struct Row10;"#};
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new(),
);
assert_eq!( assert_eq!(
all_hunks, all_hunks,
vec![ vec![
@ -2135,8 +2132,8 @@ struct Row10;"#};
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![1..3, 8..9], vec![1..=2, 8..=8],
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,
@ -2170,10 +2167,7 @@ struct Row10;"#};
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new(),
);
assert_eq!( assert_eq!(
all_hunks, all_hunks,
vec![( vec![(
@ -2189,8 +2183,8 @@ struct Row10;"#};
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), vec![5..=5]
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,

View File

@ -449,7 +449,7 @@ pub struct Editor {
show_wrap_guides: Option<bool>, show_wrap_guides: Option<bool>,
placeholder_text: Option<Arc<str>>, placeholder_text: Option<Arc<str>>,
highlight_order: usize, highlight_order: usize,
highlighted_rows: HashMap<TypeId, Vec<(usize, Range<Anchor>, Hsla)>>, highlighted_rows: HashMap<TypeId, Vec<(usize, RangeInclusive<Anchor>, Option<Hsla>)>>,
background_highlights: TreeMap<TypeId, BackgroundHighlight>, background_highlights: TreeMap<TypeId, BackgroundHighlight>,
scrollbar_marker_state: ScrollbarMarkerState, scrollbar_marker_state: ScrollbarMarkerState,
nav_history: Option<ItemNavHistory>, nav_history: Option<ItemNavHistory>,
@ -9705,7 +9705,7 @@ impl Editor {
/// If multiple anchor ranges will produce highlights for the same row, the last range added will be used. /// If multiple anchor ranges will produce highlights for the same row, the last range added will be used.
pub fn highlight_rows<T: 'static>( pub fn highlight_rows<T: 'static>(
&mut self, &mut self,
rows: Range<Anchor>, rows: RangeInclusive<Anchor>,
color: Option<Hsla>, color: Option<Hsla>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
@ -9716,9 +9716,13 @@ impl Editor {
let existing_highlight_index = let existing_highlight_index =
row_highlights.binary_search_by(|(_, highlight_range, _)| { row_highlights.binary_search_by(|(_, highlight_range, _)| {
highlight_range highlight_range
.start .start()
.cmp(&rows.start, &multi_buffer_snapshot) .cmp(&rows.start(), &multi_buffer_snapshot)
.then(highlight_range.end.cmp(&rows.end, &multi_buffer_snapshot)) .then(
highlight_range
.end()
.cmp(&rows.end(), &multi_buffer_snapshot),
)
}); });
match color { match color {
Some(color) => { Some(color) => {
@ -9728,20 +9732,22 @@ impl Editor {
}; };
row_highlights.insert( row_highlights.insert(
insert_index, insert_index,
(post_inc(&mut self.highlight_order), rows, color), (post_inc(&mut self.highlight_order), rows, Some(color)),
); );
} }
None => { None => match existing_highlight_index {
if let Ok(i) = existing_highlight_index { Ok(i) => {
row_highlights.remove(i); row_highlights.remove(i);
} }
} Err(i) => {
row_highlights
.insert(i, (post_inc(&mut self.highlight_order), rows, None));
}
},
} }
} }
hash_map::Entry::Vacant(v) => { hash_map::Entry::Vacant(v) => {
if let Some(color) = color { v.insert(vec![(post_inc(&mut self.highlight_order), rows, color)]);
v.insert(vec![(post_inc(&mut self.highlight_order), rows, color)]);
}
} }
} }
} }
@ -9754,12 +9760,12 @@ impl Editor {
/// For a highlight given context type, gets all anchor ranges that will be used for row highlighting. /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
pub fn highlighted_rows<T: 'static>( pub fn highlighted_rows<T: 'static>(
&self, &self,
) -> Option<impl Iterator<Item = (&Range<Anchor>, &Hsla)>> { ) -> Option<impl Iterator<Item = (&RangeInclusive<Anchor>, Option<&Hsla>)>> {
Some( Some(
self.highlighted_rows self.highlighted_rows
.get(&TypeId::of::<T>())? .get(&TypeId::of::<T>())?
.iter() .iter()
.map(|(_, range, color)| (range, color)), .map(|(_, range, color)| (range, color.as_ref())),
) )
} }
@ -9780,14 +9786,21 @@ impl Editor {
.fold( .fold(
BTreeMap::<u32, Hsla>::new(), BTreeMap::<u32, Hsla>::new(),
|mut unique_rows, (highlight_order, anchor_range, hsla)| { |mut unique_rows, (highlight_order, anchor_range, hsla)| {
let start_row = anchor_range.start.to_display_point(&snapshot).row(); let start_row = anchor_range.start().to_display_point(&snapshot).row();
let end_row = anchor_range.end.to_display_point(&snapshot).row(); let end_row = anchor_range.end().to_display_point(&snapshot).row();
for row in start_row..=end_row { for row in start_row..=end_row {
let used_index = let used_index =
used_highlight_orders.entry(row).or_insert(*highlight_order); used_highlight_orders.entry(row).or_insert(*highlight_order);
if highlight_order >= used_index { if highlight_order >= used_index {
*used_index = *highlight_order; *used_index = *highlight_order;
unique_rows.insert(row, *hsla); match hsla {
Some(hsla) => {
unique_rows.insert(row, *hsla);
}
None => {
unique_rows.remove(&row);
}
}
} }
} }
unique_rows unique_rows
@ -11587,6 +11600,12 @@ trait RangeToAnchorExt {
impl<T: ToOffset> RangeToAnchorExt for Range<T> { impl<T: ToOffset> RangeToAnchorExt for Range<T> {
fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> { fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end) let start_offset = self.start.to_offset(snapshot);
let end_offset = self.end.to_offset(snapshot);
if start_offset == end_offset {
snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
} else {
snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
}
} }
} }

View File

@ -9543,8 +9543,8 @@ async fn test_toggle_hunk_diff(executor: BackgroundExecutor, cx: &mut gpui::Test
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![1..2, 7..8, 9..10], vec![1..=1, 7..=7, 9..=9],
"After expanding, all git additions should be highlighted for Modified (split into added and removed) and Added hunks" "After expanding, all git additions should be highlighted for Modified (split into added and removed) and Added hunks"
); );
assert_eq!( assert_eq!(
@ -9571,7 +9571,7 @@ async fn test_toggle_hunk_diff(executor: BackgroundExecutor, cx: &mut gpui::Test
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), Vec::new(),
"After cancelling in editor, no git highlights should be left" "After cancelling in editor, no git highlights should be left"
); );
@ -9684,8 +9684,8 @@ async fn test_toggled_diff_base_change(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![9..11, 13..15], vec![9..=10, 13..=14],
"After expanding, all git additions should be highlighted for Modified (split into added and removed) and Added hunks" "After expanding, all git additions should be highlighted for Modified (split into added and removed) and Added hunks"
); );
assert_eq!( assert_eq!(
@ -9713,7 +9713,7 @@ async fn test_toggled_diff_base_change(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), Vec::new(),
"After diff base is changed, old git highlights should be removed" "After diff base is changed, old git highlights should be removed"
); );
@ -9858,8 +9858,8 @@ async fn test_fold_unfold_diff(executor: BackgroundExecutor, cx: &mut gpui::Test
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![9..11, 13..15, 19..20] vec![9..=10, 13..=14, 19..=19]
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,
@ -9923,8 +9923,8 @@ async fn test_fold_unfold_diff(executor: BackgroundExecutor, cx: &mut gpui::Test
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![5..6], vec![0..=0, 5..=5],
"Only one hunk is left not folded, its highlight should be visible" "Only one hunk is left not folded, its highlight should be visible"
); );
assert_eq!( assert_eq!(
@ -10004,8 +10004,8 @@ async fn test_fold_unfold_diff(executor: BackgroundExecutor, cx: &mut gpui::Test
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![9..11, 13..15, 19..20], vec![9..=10, 13..=14, 19..=19],
"After unfolding, all hunk diffs should be visible again" "After unfolding, all hunk diffs should be visible again"
); );
assert_eq!( assert_eq!(
@ -10172,10 +10172,7 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new(),
);
assert_eq!(all_hunks, expected_all_hunks); assert_eq!(all_hunks, expected_all_hunks);
assert_eq!(all_expanded_hunks, Vec::new()); assert_eq!(all_expanded_hunks, Vec::new());
}); });
@ -10190,8 +10187,8 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![18..19, 33..34], vec![18..=18, 33..=33],
); );
assert_eq!(all_hunks, expected_all_hunks_shifted); assert_eq!(all_hunks, expected_all_hunks_shifted);
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
@ -10205,10 +10202,7 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new(),
);
assert_eq!(all_hunks, expected_all_hunks); assert_eq!(all_hunks, expected_all_hunks);
assert_eq!(all_expanded_hunks, Vec::new()); assert_eq!(all_expanded_hunks, Vec::new());
}); });
@ -10222,8 +10216,8 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![18..19, 33..34], vec![18..=18, 33..=33],
); );
assert_eq!(all_hunks, expected_all_hunks_shifted); assert_eq!(all_hunks, expected_all_hunks_shifted);
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
@ -10237,10 +10231,7 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new(),
);
assert_eq!(all_hunks, expected_all_hunks); assert_eq!(all_hunks, expected_all_hunks);
assert_eq!(all_expanded_hunks, Vec::new()); assert_eq!(all_expanded_hunks, Vec::new());
}); });
@ -10329,8 +10320,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 4..7)] vec![("".to_string(), DiffHunkStatus::Added, 4..7)]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![4..7] vec![4..=6]
); );
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
}); });
@ -10365,8 +10356,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 4..8)] vec![("".to_string(), DiffHunkStatus::Added, 4..8)]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![4..8], vec![4..=6],
"Edited hunk should have one more line added" "Edited hunk should have one more line added"
); );
assert_eq!( assert_eq!(
@ -10406,8 +10397,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 4..9)] vec![("".to_string(), DiffHunkStatus::Added, 4..9)]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![4..9], vec![4..=6],
"Edited hunk should have one more line added" "Edited hunk should have one more line added"
); );
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
@ -10446,8 +10437,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 4..8)] vec![("".to_string(), DiffHunkStatus::Added, 4..8)]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![4..8], vec![4..=6],
"Deleting a line should shrint the hunk" "Deleting a line should shrint the hunk"
); );
assert_eq!( assert_eq!(
@ -10490,8 +10481,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 5..6)] vec![("".to_string(), DiffHunkStatus::Added, 5..6)]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![5..6] vec![5..=5]
); );
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
}); });
@ -10533,7 +10524,7 @@ async fn test_edits_around_toggled_additions(
] ]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), Vec::new(),
"Should close all stale expanded addition hunks" "Should close all stale expanded addition hunks"
); );
@ -10632,10 +10623,7 @@ async fn test_edits_around_toggled_deletions(
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new()
);
assert_eq!( assert_eq!(
all_hunks, all_hunks,
vec![( vec![(
@ -10672,7 +10660,7 @@ async fn test_edits_around_toggled_deletions(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), Vec::new(),
"Deleted hunks do not highlight current editor's background" "Deleted hunks do not highlight current editor's background"
); );
@ -10710,10 +10698,7 @@ async fn test_edits_around_toggled_deletions(
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
expanded_hunks_background_highlights(editor, &snapshot),
Vec::new()
);
assert_eq!( assert_eq!(
all_hunks, all_hunks,
vec![( vec![(
@ -10757,8 +10742,8 @@ async fn test_edits_around_toggled_deletions(
)] )]
); );
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![7..8], vec![7..=7],
"Modified expanded hunks should display additions and highlight their background" "Modified expanded hunks should display additions and highlight their background"
); );
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
@ -10851,8 +10836,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..7], vec![6..=6],
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,
@ -10894,8 +10879,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..9], vec![6..=6],
"Modified hunk should grow highlighted lines on more text additions" "Modified hunk should grow highlighted lines on more text additions"
); );
assert_eq!( assert_eq!(
@ -10940,9 +10925,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..9], vec![6..=8],
"Modified hunk should grow deleted lines on text deletions above"
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,
@ -10950,7 +10934,8 @@ async fn test_edits_around_toggled_modifications(
"const B: u32 = 42;\nconst C: u32 = 42;\n".to_string(), "const B: u32 = 42;\nconst C: u32 = 42;\n".to_string(),
DiffHunkStatus::Modified, DiffHunkStatus::Modified,
6..9 6..9
)] )],
"Modified hunk should grow deleted lines on text deletions above"
); );
assert_eq!(all_hunks, all_expanded_hunks); assert_eq!(all_hunks, all_expanded_hunks);
}); });
@ -10984,8 +10969,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..10], vec![6..=9],
"Modified hunk should grow deleted lines on text modifications above" "Modified hunk should grow deleted lines on text modifications above"
); );
assert_eq!( assert_eq!(
@ -11028,8 +11013,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..9], vec![6..=8],
"Modified hunk should grow shrink lines on modification lines removal" "Modified hunk should grow shrink lines on modification lines removal"
); );
assert_eq!( assert_eq!(
@ -11069,7 +11054,7 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
Vec::new(), Vec::new(),
"Modified hunk should turn into a removed one on all modified lines removal" "Modified hunk should turn into a removed one on all modified lines removal"
); );
@ -11172,8 +11157,8 @@ async fn test_multiple_expanded_hunks_merge(
let all_hunks = editor_hunks(editor, &snapshot, cx); let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx); let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!( assert_eq!(
expanded_hunks_background_highlights(editor, &snapshot), expanded_hunks_background_highlights(editor, cx),
vec![6..7], vec![6..=6],
); );
assert_eq!( assert_eq!(
all_hunks, all_hunks,

View File

@ -1,4 +1,7 @@
use std::{ops::Range, sync::Arc}; use std::{
ops::{Range, RangeInclusive},
sync::Arc,
};
use collections::{hash_map, HashMap, HashSet}; use collections::{hash_map, HashMap, HashSet};
use git::diff::{DiffHunk, DiffHunkStatus}; use git::diff::{DiffHunk, DiffHunkStatus};
@ -14,8 +17,8 @@ use util::{debug_panic, RangeExt};
use crate::{ use crate::{
git::{diff_hunk_to_display, DisplayDiffHunk}, git::{diff_hunk_to_display, DisplayDiffHunk},
hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight, hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight,
Editor, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks, ToDisplayPoint, Editor, EditorSnapshot, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks,
ToggleHunkDiff, ToDisplayPoint, ToggleHunkDiff,
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -184,7 +187,11 @@ impl Editor {
} }
for removed_rows in highlights_to_remove { for removed_rows in highlights_to_remove {
editor.highlight_rows::<DiffRowHighlight>(removed_rows, None, cx); editor.highlight_rows::<DiffRowHighlight>(
to_inclusive_row_range(removed_rows, &snapshot),
None,
cx,
);
} }
editor.remove_blocks(blocks_to_remove, None, cx); editor.remove_blocks(blocks_to_remove, None, cx);
for hunk in hunks_to_expand { for hunk in hunks_to_expand {
@ -216,9 +223,9 @@ impl Editor {
let hunk_end = hunk.multi_buffer_range.end; let hunk_end = hunk.multi_buffer_range.end;
let buffer = self.buffer().clone(); 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 snapshot = buffer.snapshot(cx); let hunk = buffer_diff_hunk(&snapshot.buffer_snapshot, multi_buffer_row_range.clone())?;
let hunk = buffer_diff_hunk(&snapshot, multi_buffer_row_range.clone())?;
let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx); let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx);
if buffer_ranges.len() == 1 { if buffer_ranges.len() == 1 {
let (buffer, _, _) = buffer_ranges.pop()?; let (buffer, _, _) = buffer_ranges.pop()?;
@ -256,7 +263,7 @@ impl Editor {
} }
DiffHunkStatus::Added => { DiffHunkStatus::Added => {
self.highlight_rows::<DiffRowHighlight>( self.highlight_rows::<DiffRowHighlight>(
hunk_start..hunk_end, to_inclusive_row_range(hunk_start..hunk_end, &snapshot),
Some(added_hunk_color(cx)), Some(added_hunk_color(cx)),
cx, cx,
); );
@ -264,13 +271,16 @@ impl Editor {
} }
DiffHunkStatus::Modified => { DiffHunkStatus::Modified => {
self.highlight_rows::<DiffRowHighlight>( self.highlight_rows::<DiffRowHighlight>(
hunk_start..hunk_end, to_inclusive_row_range(hunk_start..hunk_end, &snapshot),
Some(added_hunk_color(cx)), Some(added_hunk_color(cx)),
cx, cx,
); );
self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx) self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx)
} }
}; };
if hunk_start.cmp(&hunk_end, &multi_buffer_snapshot).is_gt() {
eprintln!("@######################!!!!!!!!!!!!!");
};
self.expanded_hunks.hunks.insert( self.expanded_hunks.hunks.insert(
block_insert_index, block_insert_index,
ExpandedHunk { ExpandedHunk {
@ -461,7 +471,11 @@ impl Editor {
}); });
for removed_rows in highlights_to_remove { for removed_rows in highlights_to_remove {
editor.highlight_rows::<DiffRowHighlight>(removed_rows, None, cx); editor.highlight_rows::<DiffRowHighlight>(
to_inclusive_row_range(removed_rows, &snapshot),
None,
cx,
);
} }
editor.remove_blocks(blocks_to_remove, None, cx); editor.remove_blocks(blocks_to_remove, None, cx);
@ -565,7 +579,7 @@ fn editor_with_deleted_text(
.buffer_snapshot .buffer_snapshot
.anchor_after(editor.buffer.read(cx).len(cx)); .anchor_after(editor.buffer.read(cx).len(cx));
editor.highlight_rows::<DiffRowHighlight>(start..end, Some(deleted_color), cx); editor.highlight_rows::<DiffRowHighlight>(start..=end, Some(deleted_color), cx);
let hunk_related_subscription = cx.on_blur(&editor.focus_handle, |editor, cx| { let hunk_related_subscription = cx.on_blur(&editor.focus_handle, |editor, cx| {
editor.change_selections(None, cx, |s| { editor.change_selections(None, cx, |s| {
s.try_cancel(); s.try_cancel();
@ -619,3 +633,18 @@ fn buffer_diff_hunk(
} }
None None
} }
fn to_inclusive_row_range(
row_range: Range<Anchor>,
snapshot: &EditorSnapshot,
) -> RangeInclusive<Anchor> {
let mut display_row_range =
row_range.start.to_display_point(snapshot)..row_range.end.to_display_point(snapshot);
if display_row_range.end.row() > display_row_range.start.row() {
*display_row_range.end.row_mut() -= 1;
}
let point_range = display_row_range.start.to_point(&snapshot.display_snapshot)
..display_row_range.end.to_point(&snapshot.display_snapshot);
let new_range = point_range.to_anchors(&snapshot.buffer_snapshot);
new_range.start..=new_range.end
}

View File

@ -148,18 +148,31 @@ pub fn expanded_hunks(
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub fn expanded_hunks_background_highlights( pub fn expanded_hunks_background_highlights(
editor: &Editor, editor: &mut Editor,
snapshot: &DisplaySnapshot, cx: &mut gpui::WindowContext,
) -> Vec<core::ops::Range<u32>> { ) -> Vec<std::ops::RangeInclusive<u32>> {
use itertools::Itertools; let mut highlights = Vec::new();
editor let mut range_start = 0;
.highlighted_rows::<crate::DiffRowHighlight>() let mut previous_highlighted_row = None;
.into_iter() for (highlighted_row, _) in editor.highlighted_display_rows(collections::HashSet::default(), cx)
.flatten() {
.map(|(range, _)| { match previous_highlighted_row {
range.start.to_display_point(snapshot).row()..range.end.to_display_point(snapshot).row() Some(previous_row) => {
}) if previous_row + 1 != highlighted_row {
.unique() highlights.push(range_start..=previous_row);
.collect() range_start = highlighted_row;
}
}
None => {
range_start = highlighted_row;
}
}
previous_highlighted_row = Some(highlighted_row);
}
if let Some(previous_row) = previous_highlighted_row {
highlights.push(range_start..=previous_row);
}
highlights
} }

View File

@ -120,7 +120,7 @@ impl GoToLine {
let anchor = snapshot.buffer_snapshot.anchor_before(point); let anchor = snapshot.buffer_snapshot.anchor_before(point);
active_editor.clear_row_highlights::<GoToLineRowHighlights>(); active_editor.clear_row_highlights::<GoToLineRowHighlights>();
active_editor.highlight_rows::<GoToLineRowHighlights>( active_editor.highlight_rows::<GoToLineRowHighlights>(
anchor..anchor, anchor..=anchor,
Some(cx.theme().colors().editor_highlighted_line_background), Some(cx.theme().colors().editor_highlighted_line_background),
cx, cx,
); );

View File

@ -142,7 +142,7 @@ impl OutlineViewDelegate {
self.active_editor.update(cx, |active_editor, cx| { self.active_editor.update(cx, |active_editor, cx| {
active_editor.clear_row_highlights::<OutlineRowHighlights>(); active_editor.clear_row_highlights::<OutlineRowHighlights>();
active_editor.highlight_rows::<OutlineRowHighlights>( active_editor.highlight_rows::<OutlineRowHighlights>(
outline_item.range.clone(), outline_item.range.start..=outline_item.range.end,
Some(cx.theme().colors().editor_highlighted_line_background), Some(cx.theme().colors().editor_highlighted_line_background),
cx, cx,
); );
@ -243,7 +243,7 @@ impl PickerDelegate for OutlineViewDelegate {
.and_then(|highlights| highlights.into_iter().next().map(|(rows, _)| rows.clone())) .and_then(|highlights| highlights.into_iter().next().map(|(rows, _)| rows.clone()))
{ {
active_editor.change_selections(Some(Autoscroll::center()), cx, |s| { active_editor.change_selections(Some(Autoscroll::center()), cx, |s| {
s.select_ranges([rows.start..rows.start]) s.select_ranges([*rows.start()..*rows.start()])
}); });
active_editor.clear_row_highlights::<OutlineRowHighlights>(); active_editor.clear_row_highlights::<OutlineRowHighlights>();
active_editor.focus(cx); active_editor.focus(cx);