diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 15f7a37ad61afca40c3a1443cb5784d52e6ebd9e..be60041277e97289bc7a3fdf43794dc3a72047e4 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -472,7 +472,6 @@ impl DisplayMap { } } - // TODO(split-diff) figure out how to free the LHS from having to build a block map before this is called pub(crate) fn set_companion( &mut self, companion: Option<(Entity, Entity)>, @@ -485,26 +484,31 @@ impl DisplayMap { let Some((_, companion)) = self.companion.take() else { return; }; - let (snapshot, edits) = self.sync_through_wrap(cx); - let edits = edits.compose([text::Edit { - old: WrapRow(0)..snapshot.max_point().row(), - new: WrapRow(0)..snapshot.max_point().row(), + assert_eq!(self.entity_id, companion.read(cx).rhs_display_map_id); + let (snapshot, _edits) = self.sync_through_wrap(cx); + let edits = Patch::new(vec![text::Edit { + old: WrapRow(0) + ..self.block_map.wrap_snapshot.borrow().max_point().row() + WrapRow(1), + new: WrapRow(0)..snapshot.max_point().row() + WrapRow(1), }]); - self.block_map.write(snapshot, edits, None).remove( - companion + self.block_map.deferred_edits.set(edits); + self.block_map.retain_blocks_raw(|block| { + if companion .read(cx) .lhs_custom_block_to_balancing_block .borrow() .values() - .copied() - .collect(), - ); + .any(|id| *id == block.id) + { + return false; + } + true + }); return; }; assert_eq!(self.entity_id, companion.read(cx).rhs_display_map_id); - // Note, throwing away the wrap edits because we're going to recompute the maximal range for the block map regardless - let old_max_row = self.block_map.wrap_snapshot.borrow().max_point().row(); + // Note, throwing away the wrap edits because we defer spacer computation to the first render. let snapshot = { let edits = self.buffer_subscription.consume(); let snapshot = self.buffer.read(cx).snapshot(cx); @@ -528,28 +532,16 @@ impl DisplayMap { snapshot }; - let (companion_wrap_snapshot, companion_wrap_edits) = + let (companion_wrap_snapshot, _companion_wrap_edits) = companion_display_map.update(cx, |dm, cx| dm.sync_through_wrap(cx)); - let edits = Patch::new( - [text::Edit { - old: WrapRow(0)..old_max_row, - new: WrapRow(0)..snapshot.max_point().row(), - }] - .into_iter() - .collect(), - ); + let edits = Patch::new(vec![text::Edit { + old: WrapRow(0)..self.block_map.wrap_snapshot.borrow().max_point().row() + WrapRow(1), + new: WrapRow(0)..snapshot.max_point().row() + WrapRow(1), + }]); + self.block_map.deferred_edits.set(edits); - let reader = self.block_map.read( - snapshot.clone(), - edits.clone(), - Some(CompanionView::new( - self.entity_id, - &companion_wrap_snapshot, - &companion_wrap_edits, - companion.read(cx), - )), - ); + let all_blocks: Vec<_> = self.block_map.blocks_raw().map(Clone::clone).collect(); companion_display_map.update(cx, |companion_display_map, cx| { for my_buffer in self.folded_buffers() { @@ -563,7 +555,7 @@ impl DisplayMap { .folded_buffers .insert(*their_buffer); } - for block in reader.blocks { + for block in all_blocks { let Some(their_block) = block_map::balancing_block( &block.properties(), snapshot.buffer(), @@ -583,16 +575,21 @@ impl DisplayMap { .insert(block.id, their_id); }); } - companion_display_map.block_map.read( - companion_wrap_snapshot, - companion_wrap_edits, - Some(CompanionView::new( - companion_display_map.entity_id, - &snapshot, - &edits, - companion.read(cx), - )), - ); + let companion_edits = Patch::new(vec![text::Edit { + old: WrapRow(0) + ..companion_display_map + .block_map + .wrap_snapshot + .borrow() + .max_point() + .row() + + WrapRow(1), + new: WrapRow(0)..companion_wrap_snapshot.max_point().row() + WrapRow(1), + }]); + companion_display_map + .block_map + .deferred_edits + .set(companion_edits); companion_display_map.companion = Some((this, companion.clone())); }); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index f0547332d00d60d3c5ccc4407add977a659c6ab6..de9d94fdb94b08c05efb582f2f56d4b8078b1ead 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -16,7 +16,7 @@ use multi_buffer::{ }; use parking_lot::Mutex; use std::{ - cell::RefCell, + cell::{Cell, RefCell}, cmp::{self, Ordering}, fmt::Debug, ops::{Deref, DerefMut, Not, Range, RangeBounds, RangeInclusive}, @@ -45,6 +45,7 @@ pub struct BlockMap { excerpt_header_height: u32, pub(super) folded_buffers: HashSet, buffers_with_disabled_headers: HashSet, + pub(super) deferred_edits: Cell>, } pub struct BlockMapReader<'a> { @@ -620,6 +621,7 @@ impl BlockMap { wrap_snapshot: RefCell::new(wrap_snapshot.clone()), buffer_header_height, excerpt_header_height, + deferred_edits: Cell::default(), }; map.sync( &wrap_snapshot, @@ -747,6 +749,11 @@ impl BlockMap { .retain(|id, _| !ids_to_remove.contains(id)); } + // Warning: doesn't sync the block map, use advisedly + pub(crate) fn blocks_raw(&self) -> impl Iterator> { + self.custom_blocks.iter() + } + #[ztracing::instrument(skip_all, fields(edits = ?edits))] fn sync( &self, @@ -756,6 +763,8 @@ impl BlockMap { ) { let buffer = wrap_snapshot.buffer_snapshot(); + edits = self.deferred_edits.take().compose(edits); + // Handle changing the last excerpt if it is empty. if buffer.trailing_excerpt_update_count() != self diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c157c37eb460bcf2db5b697e4ae1101686d43c36..05b4c1d2095fd867ec67f26f5f5c7f5f028e4966 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -20682,11 +20682,7 @@ impl Editor { fn toggle_single_diff_hunk(&mut self, range: Range, cx: &mut Context) { self.buffer.update(cx, |buffer, cx| { - let snapshot = buffer.snapshot(cx); - let excerpt_id = range.end.excerpt_id; - let point_range = range.to_point(&snapshot); - let expand = !buffer.single_hunk_is_expanded(range, cx); - buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx); + buffer.toggle_single_diff_hunk(range, cx); }) } diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index a5266874a0d24c61816212ab7fa100c01d458567..303fdfad30378214c084fdd285693e2f14b67a25 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -2682,7 +2682,25 @@ impl MultiBuffer { pub fn set_show_deleted_hunks(&mut self, show: bool, cx: &mut Context) { self.snapshot.get_mut().show_deleted_hunks = show; - self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx); + + self.sync_mut(cx); + + let old_len = self.snapshot.borrow().len(); + + let ranges = std::iter::once((Point::zero()..Point::MAX, ExcerptId::max())); + let _ = self.expand_or_collapse_diff_hunks_inner(ranges, true, cx); + + let new_len = self.snapshot.borrow().len(); + + self.subscriptions.publish(vec![Edit { + old: MultiBufferOffset(0)..old_len, + new: MultiBufferOffset(0)..new_len, + }]); + + cx.emit(Event::DiffHunksToggled); + cx.emit(Event::Edited { + edited_buffer: None, + }); } pub fn set_use_extended_diff_range(&mut self, use_extended: bool, _cx: &mut Context) { @@ -2740,9 +2758,9 @@ impl MultiBuffer { ranges: impl IntoIterator, ExcerptId)>, expand: bool, cx: &mut Context, - ) { + ) -> Vec> { if self.snapshot.borrow().all_diff_hunks_expanded && !expand { - return; + return Vec::new(); } self.sync_mut(cx); let mut snapshot = self.snapshot.get_mut(); @@ -2768,18 +2786,11 @@ impl MultiBuffer { } } - let edits = Self::sync_diff_transforms( + Self::sync_diff_transforms( &mut snapshot, excerpt_edits, DiffChangeKind::ExpandOrCollapseHunks { expand }, - ); - if !edits.is_empty() { - self.subscriptions.publish(edits); - } - cx.emit(Event::DiffHunksToggled); - cx.emit(Event::Edited { - edited_buffer: None, - }); + ) } pub fn expand_or_collapse_diff_hunks( @@ -2798,7 +2809,14 @@ impl MultiBuffer { }; (range.start..peek_end, end_excerpt_id) }); - self.expand_or_collapse_diff_hunks_inner(ranges, expand, cx); + let edits = self.expand_or_collapse_diff_hunks_inner(ranges, expand, cx); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } + cx.emit(Event::DiffHunksToggled); + cx.emit(Event::Edited { + edited_buffer: None, + }); } pub fn resize_excerpt( @@ -3601,6 +3619,22 @@ impl MultiBuffer { ); did_extend } + + pub fn toggle_single_diff_hunk(&mut self, range: Range, cx: &mut Context) { + let snapshot = self.snapshot(cx); + let excerpt_id = range.end.excerpt_id; + let point_range = range.to_point(&snapshot); + let expand = !self.single_hunk_is_expanded(range, cx); + let edits = + self.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } + cx.emit(Event::DiffHunksToggled); + cx.emit(Event::Edited { + edited_buffer: None, + }); + } } fn build_excerpt_ranges(