@@ -449,7 +449,7 @@ pub struct Editor {
show_wrap_guides: Option<bool>,
placeholder_text: Option<Arc<str>>,
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>,
scrollbar_marker_state: ScrollbarMarkerState,
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.
pub fn highlight_rows<T: 'static>(
&mut self,
- rows: Range<Anchor>,
+ rows: RangeInclusive<Anchor>,
color: Option<Hsla>,
cx: &mut ViewContext<Self>,
) {
@@ -9716,9 +9716,13 @@ impl Editor {
let existing_highlight_index =
row_highlights.binary_search_by(|(_, highlight_range, _)| {
highlight_range
- .start
- .cmp(&rows.start, &multi_buffer_snapshot)
- .then(highlight_range.end.cmp(&rows.end, &multi_buffer_snapshot))
+ .start()
+ .cmp(&rows.start(), &multi_buffer_snapshot)
+ .then(
+ highlight_range
+ .end()
+ .cmp(&rows.end(), &multi_buffer_snapshot),
+ )
});
match color {
Some(color) => {
@@ -9728,20 +9732,22 @@ impl Editor {
};
row_highlights.insert(
insert_index,
- (post_inc(&mut self.highlight_order), rows, color),
+ (post_inc(&mut self.highlight_order), rows, Some(color)),
);
}
- None => {
- if let Ok(i) = existing_highlight_index {
+ None => match existing_highlight_index {
+ Ok(i) => {
row_highlights.remove(i);
}
- }
+ Err(i) => {
+ row_highlights
+ .insert(i, (post_inc(&mut self.highlight_order), rows, None));
+ }
+ },
}
}
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.
pub fn highlighted_rows<T: 'static>(
&self,
- ) -> Option<impl Iterator<Item = (&Range<Anchor>, &Hsla)>> {
+ ) -> Option<impl Iterator<Item = (&RangeInclusive<Anchor>, Option<&Hsla>)>> {
Some(
self.highlighted_rows
.get(&TypeId::of::<T>())?
.iter()
- .map(|(_, range, color)| (range, color)),
+ .map(|(_, range, color)| (range, color.as_ref())),
)
}
@@ -9780,14 +9786,21 @@ impl Editor {
.fold(
BTreeMap::<u32, Hsla>::new(),
|mut unique_rows, (highlight_order, anchor_range, hsla)| {
- let start_row = anchor_range.start.to_display_point(&snapshot).row();
- let end_row = anchor_range.end.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();
for row in start_row..=end_row {
let used_index =
used_highlight_orders.entry(row).or_insert(*highlight_order);
if highlight_order >= used_index {
*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
@@ -11587,6 +11600,12 @@ trait RangeToAnchorExt {
impl<T: ToOffset> RangeToAnchorExt for Range<T> {
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)
+ }
}
}
@@ -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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![1..2, 7..8, 9..10],
+ expanded_hunks_background_highlights(editor, cx),
+ 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"
);
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_expanded_hunks = expanded_hunks(editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
+ expanded_hunks_background_highlights(editor, cx),
Vec::new(),
"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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![9..11, 13..15],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![9..=10, 13..=14],
"After expanding, all git additions should be highlighted for Modified (split into added and removed) and Added hunks"
);
assert_eq!(
@@ -9713,7 +9713,7 @@ async fn test_toggled_diff_base_change(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
+ expanded_hunks_background_highlights(editor, cx),
Vec::new(),
"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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![9..11, 13..15, 19..20]
+ expanded_hunks_background_highlights(editor, cx),
+ vec![9..=10, 13..=14, 19..=19]
);
assert_eq!(
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![5..6],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![0..=0, 5..=5],
"Only one hunk is left not folded, its highlight should be visible"
);
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![9..11, 13..15, 19..20],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![9..=10, 13..=14, 19..=19],
"After unfolding, all hunk diffs should be visible again"
);
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 all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
- assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- Vec::new(),
- );
+ assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
assert_eq!(all_hunks, expected_all_hunks);
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![18..19, 33..34],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![18..=18, 33..=33],
);
assert_eq!(all_hunks, expected_all_hunks_shifted);
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 all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
- assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- Vec::new(),
- );
+ assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
assert_eq!(all_hunks, expected_all_hunks);
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![18..19, 33..34],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![18..=18, 33..=33],
);
assert_eq!(all_hunks, expected_all_hunks_shifted);
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 all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
- assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- Vec::new(),
- );
+ assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
assert_eq!(all_hunks, expected_all_hunks);
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)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![4..7]
+ expanded_hunks_background_highlights(editor, cx),
+ vec![4..=6]
);
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)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![4..8],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![4..=6],
"Edited hunk should have one more line added"
);
assert_eq!(
@@ -10406,8 +10397,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 4..9)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![4..9],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![4..=6],
"Edited hunk should have one more line added"
);
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)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![4..8],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![4..=6],
"Deleting a line should shrint the hunk"
);
assert_eq!(
@@ -10490,8 +10481,8 @@ async fn test_edits_around_toggled_additions(
vec![("".to_string(), DiffHunkStatus::Added, 5..6)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![5..6]
+ expanded_hunks_background_highlights(editor, cx),
+ vec![5..=5]
);
assert_eq!(all_hunks, all_expanded_hunks);
});
@@ -10533,7 +10524,7 @@ async fn test_edits_around_toggled_additions(
]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
+ expanded_hunks_background_highlights(editor, cx),
Vec::new(),
"Should close all stale expanded addition hunks"
);
@@ -10632,10 +10623,7 @@ async fn test_edits_around_toggled_deletions(
let snapshot = editor.snapshot(cx);
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
- assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- Vec::new()
- );
+ assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
assert_eq!(
all_hunks,
vec![(
@@ -10672,7 +10660,7 @@ async fn test_edits_around_toggled_deletions(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
+ expanded_hunks_background_highlights(editor, cx),
Vec::new(),
"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 all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
- assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- Vec::new()
- );
+ assert_eq!(expanded_hunks_background_highlights(editor, cx), Vec::new());
assert_eq!(
all_hunks,
vec![(
@@ -10757,8 +10742,8 @@ async fn test_edits_around_toggled_deletions(
)]
);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![7..8],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![7..=7],
"Modified expanded hunks should display additions and highlight their background"
);
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..7],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=6],
);
assert_eq!(
all_hunks,
@@ -10894,8 +10879,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..9],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=6],
"Modified hunk should grow highlighted lines on more text additions"
);
assert_eq!(
@@ -10940,9 +10925,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..9],
- "Modified hunk should grow deleted lines on text deletions above"
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=8],
);
assert_eq!(
all_hunks,
@@ -10950,7 +10934,8 @@ async fn test_edits_around_toggled_modifications(
"const B: u32 = 42;\nconst C: u32 = 42;\n".to_string(),
DiffHunkStatus::Modified,
6..9
- )]
+ )],
+ "Modified hunk should grow deleted lines on text deletions above"
);
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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..10],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=9],
"Modified hunk should grow deleted lines on text modifications above"
);
assert_eq!(
@@ -11028,8 +11013,8 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..9],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=8],
"Modified hunk should grow shrink lines on modification lines removal"
);
assert_eq!(
@@ -11069,7 +11054,7 @@ async fn test_edits_around_toggled_modifications(
let all_hunks = editor_hunks(editor, &snapshot, cx);
let all_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
+ expanded_hunks_background_highlights(editor, cx),
Vec::new(),
"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_expanded_hunks = expanded_hunks(&editor, &snapshot, cx);
assert_eq!(
- expanded_hunks_background_highlights(editor, &snapshot),
- vec![6..7],
+ expanded_hunks_background_highlights(editor, cx),
+ vec![6..=6],
);
assert_eq!(
all_hunks,
@@ -1,4 +1,7 @@
-use std::{ops::Range, sync::Arc};
+use std::{
+ ops::{Range, RangeInclusive},
+ sync::Arc,
+};
use collections::{hash_map, HashMap, HashSet};
use git::diff::{DiffHunk, DiffHunkStatus};
@@ -14,8 +17,8 @@ use util::{debug_panic, RangeExt};
use crate::{
git::{diff_hunk_to_display, DisplayDiffHunk},
hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight,
- Editor, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks, ToDisplayPoint,
- ToggleHunkDiff,
+ Editor, EditorSnapshot, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks,
+ ToDisplayPoint, ToggleHunkDiff,
};
#[derive(Debug, Clone)]
@@ -184,7 +187,11 @@ impl Editor {
}
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);
for hunk in hunks_to_expand {
@@ -216,9 +223,9 @@ impl Editor {
let hunk_end = hunk.multi_buffer_range.end;
let buffer = self.buffer().clone();
+ let snapshot = self.snapshot(cx);
let (diff_base_buffer, deleted_text_lines) = buffer.update(cx, |buffer, cx| {
- let snapshot = buffer.snapshot(cx);
- let hunk = buffer_diff_hunk(&snapshot, multi_buffer_row_range.clone())?;
+ let hunk = buffer_diff_hunk(&snapshot.buffer_snapshot, multi_buffer_row_range.clone())?;
let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx);
if buffer_ranges.len() == 1 {
let (buffer, _, _) = buffer_ranges.pop()?;
@@ -256,7 +263,7 @@ impl Editor {
}
DiffHunkStatus::Added => {
self.highlight_rows::<DiffRowHighlight>(
- hunk_start..hunk_end,
+ to_inclusive_row_range(hunk_start..hunk_end, &snapshot),
Some(added_hunk_color(cx)),
cx,
);
@@ -264,13 +271,16 @@ impl Editor {
}
DiffHunkStatus::Modified => {
self.highlight_rows::<DiffRowHighlight>(
- hunk_start..hunk_end,
+ to_inclusive_row_range(hunk_start..hunk_end, &snapshot),
Some(added_hunk_color(cx)),
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(
block_insert_index,
ExpandedHunk {
@@ -461,7 +471,11 @@ impl Editor {
});
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);
@@ -565,7 +579,7 @@ fn editor_with_deleted_text(
.buffer_snapshot
.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| {
editor.change_selections(None, cx, |s| {
s.try_cancel();
@@ -619,3 +633,18 @@ fn buffer_diff_hunk(
}
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
+}