@@ -36,9 +36,7 @@ use std::{
any::type_name,
borrow::Cow,
cell::{Cell, Ref, RefCell},
- cmp,
- collections::VecDeque,
- fmt::{self, Debug},
+ cmp, fmt,
future::Future,
io,
iter::{self, FromIterator},
@@ -63,9 +61,6 @@ pub use self::path_key::PathKey;
#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ExcerptId(u32);
-#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct BaseTextRow(pub u32);
-
/// One or more [`Buffers`](Buffer) being edited in a single view.
///
/// See <https://zed.dev/features#multi-buffers>
@@ -92,14 +87,6 @@ pub struct MultiBuffer {
/// The writing capability of the multi-buffer.
capability: Capability,
buffer_changed_since_sync: Rc<Cell<bool>>,
- follower: Option<Entity<MultiBuffer>>,
- filter_mode: Option<MultiBufferFilterMode>,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum MultiBufferFilterMode {
- KeepInsertions,
- KeepDeletions,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -152,8 +139,6 @@ pub struct MultiBufferDiffHunk {
pub diff_base_byte_range: Range<BufferOffset>,
/// Whether or not this hunk also appears in the 'secondary diff'.
pub secondary_status: DiffHunkSecondaryStatus,
- /// The word diffs for this hunk.
- pub word_diffs: Vec<Range<MultiBufferOffset>>,
}
impl MultiBufferDiffHunk {
@@ -563,33 +548,25 @@ pub struct MultiBufferSnapshot {
}
#[derive(Debug, Clone)]
-/// A piece of text in the multi-buffer
enum DiffTransform {
- Unmodified {
+ BufferContent {
summary: MBTextSummary,
- },
- InsertedHunk {
- summary: MBTextSummary,
- hunk_info: DiffTransformHunkInfo,
- },
- FilteredInsertedHunk {
- summary: MBTextSummary,
- hunk_info: DiffTransformHunkInfo,
+ inserted_hunk_info: Option<DiffTransformHunkInfo>,
},
DeletedHunk {
summary: TextSummary,
buffer_id: BufferId,
hunk_info: DiffTransformHunkInfo,
+ base_text_byte_range: Range<usize>,
has_trailing_newline: bool,
},
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug)]
struct DiffTransformHunkInfo {
excerpt_id: ExcerptId,
hunk_start_anchor: text::Anchor,
hunk_secondary_status: DiffHunkSecondaryStatus,
- base_text_byte_range: Range<usize>,
}
impl Eq for DiffTransformHunkInfo {}
@@ -616,15 +593,6 @@ pub struct ExcerptInfo {
pub end_row: MultiBufferRow,
}
-/// Used with [`MultiBuffer::push_buffer_content_transform`]
-#[derive(Clone, Debug)]
-struct CurrentInsertedHunk {
- hunk_excerpt_start: ExcerptOffset,
- insertion_end_offset: ExcerptOffset,
- hunk_info: DiffTransformHunkInfo,
- is_filtered: bool,
-}
-
impl std::fmt::Debug for ExcerptInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(type_name::<Self>())
@@ -664,7 +632,6 @@ pub struct ExpandInfo {
pub struct RowInfo {
pub buffer_id: Option<BufferId>,
pub buffer_row: Option<u32>,
- pub base_text_row: Option<BaseTextRow>,
pub multibuffer_row: Option<MultiBufferRow>,
pub diff_status: Option<buffer_diff::DiffHunkStatus>,
pub expand_info: Option<ExpandInfo>,
@@ -960,12 +927,10 @@ impl<'a, MBD: MultiBufferDimension> Dimension<'a, DiffTransformSummary> for Diff
struct MultiBufferCursor<'a, MBD, BD> {
excerpts: Cursor<'a, 'static, Excerpt, ExcerptDimension<MBD>>,
diff_transforms: Cursor<'a, 'static, DiffTransform, DiffTransforms<MBD>>,
- snapshot: &'a MultiBufferSnapshot,
+ diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>,
cached_region: Option<MultiBufferRegion<'a, MBD, BD>>,
}
-/// Matches transformations to an item
-/// This is essentially a more detailed version of DiffTransform
#[derive(Clone)]
struct MultiBufferRegion<'a, MBD, BD> {
buffer: &'a BufferSnapshot,
@@ -973,21 +938,10 @@ struct MultiBufferRegion<'a, MBD, BD> {
diff_hunk_status: Option<DiffHunkStatus>,
excerpt: &'a Excerpt,
buffer_range: Range<BD>,
- diff_base_byte_range: Option<Range<usize>>,
range: Range<MBD>,
has_trailing_newline: bool,
}
-impl<'a, MBD, BD> MultiBufferRegion<'a, MBD, BD>
-where
- MBD: Ord,
- BD: Ord,
-{
- fn is_filtered(&self) -> bool {
- self.range.is_empty() && self.buffer_range.is_empty() && self.diff_hunk_status == None
- }
-}
-
struct ExcerptChunks<'a> {
excerpt_id: ExcerptId,
content_chunks: BufferChunks<'a>,
@@ -1100,8 +1054,6 @@ impl MultiBuffer {
paths_by_excerpt: Default::default(),
buffer_changed_since_sync: Default::default(),
history: History::default(),
- follower: None,
- filter_mode: None,
}
}
@@ -1135,8 +1087,8 @@ impl MultiBuffer {
Self {
snapshot: RefCell::new(self.snapshot.borrow().clone()),
buffers: buffers,
- excerpts_by_path: self.excerpts_by_path.clone(),
- paths_by_excerpt: self.paths_by_excerpt.clone(),
+ excerpts_by_path: Default::default(),
+ paths_by_excerpt: Default::default(),
diffs: diff_bases,
subscriptions: Default::default(),
singleton: self.singleton,
@@ -1144,46 +1096,6 @@ impl MultiBuffer {
history: self.history.clone(),
title: self.title.clone(),
buffer_changed_since_sync,
- follower: None,
- filter_mode: None,
- }
- }
-
- pub fn get_or_create_follower(&mut self, cx: &mut Context<Self>) -> Entity<MultiBuffer> {
- use gpui::AppContext as _;
-
- if let Some(follower) = &self.follower {
- return follower.clone();
- }
-
- let follower = cx.new(|cx| self.clone(cx));
- follower.update(cx, |follower, _cx| {
- follower.capability = Capability::ReadOnly;
- });
- self.follower = Some(follower.clone());
- follower
- }
-
- pub fn set_filter_mode(&mut self, new_mode: Option<MultiBufferFilterMode>) {
- self.filter_mode = new_mode;
- let excerpt_len = self
- .snapshot
- .get_mut()
- .diff_transforms
- .summary()
- .excerpt_len();
- let edits = Self::sync_diff_transforms(
- self.snapshot.get_mut(),
- vec![Edit {
- old: ExcerptDimension(MultiBufferOffset(0))..excerpt_len,
- new: ExcerptDimension(MultiBufferOffset(0))..excerpt_len,
- }],
- // TODO(split-diff) is this right?
- DiffChangeKind::BufferEdited,
- new_mode,
- );
- if !edits.is_empty() {
- self.subscriptions.publish(edits);
}
}
@@ -1666,7 +1578,7 @@ impl MultiBuffer {
cx: &mut Context<Self>,
) -> Vec<ExcerptId>
where
- O: text::ToOffset + Clone,
+ O: text::ToOffset,
{
self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
}
@@ -1704,7 +1616,7 @@ impl MultiBuffer {
cx: &mut Context<Self>,
) -> Vec<ExcerptId>
where
- O: text::ToOffset + Clone,
+ O: text::ToOffset,
{
let mut ids = Vec::new();
let mut next_excerpt_id =
@@ -1733,13 +1645,10 @@ impl MultiBuffer {
ranges: impl IntoIterator<Item = (ExcerptId, ExcerptRange<O>)>,
cx: &mut Context<Self>,
) where
- O: text::ToOffset + Clone,
+ O: text::ToOffset,
{
- // TODO(split-diff) see if it's worth time avoiding collecting here later
- let collected_ranges: Vec<_> = ranges.into_iter().collect();
-
assert_eq!(self.history.transaction_depth(), 0);
- let mut ranges = collected_ranges.iter().cloned().peekable();
+ let mut ranges = ranges.into_iter().peekable();
if ranges.peek().is_none() {
return Default::default();
}
@@ -1839,23 +1748,11 @@ impl MultiBuffer {
new: edit_start..edit_end,
}],
DiffChangeKind::BufferEdited,
- self.filter_mode,
);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.insert_excerpts_with_ids_after(
- prev_excerpt_id,
- buffer.clone(),
- collected_ranges,
- cx,
- );
- })
- }
-
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -1905,16 +1802,10 @@ impl MultiBuffer {
new: start..start,
}],
DiffChangeKind::BufferEdited,
- self.filter_mode,
);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.clear(cx);
- })
- }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2203,22 +2094,10 @@ impl MultiBuffer {
snapshot.trailing_excerpt_update_count += 1;
}
- let edits = Self::sync_diff_transforms(
- &mut snapshot,
- edits,
- DiffChangeKind::BufferEdited,
- self.filter_mode,
- );
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
-
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.remove_excerpts(ids.clone(), cx);
- })
- }
-
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2374,7 +2253,6 @@ impl MultiBuffer {
DiffChangeKind::DiffUpdated {
base_changed: base_text_changed,
},
- self.filter_mode,
);
if !edits.is_empty() {
self.subscriptions.publish(edits);
@@ -2537,14 +2415,7 @@ impl MultiBuffer {
text::Anchor::min_max_range_for_buffer(buffer_id),
cx,
);
- self.diffs
- .insert(buffer_id, DiffState::new(diff.clone(), cx));
-
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.add_diff(diff, cx);
- })
- }
+ self.diffs.insert(buffer_id, DiffState::new(diff, cx));
}
pub fn diff_for(&self, buffer_id: BufferId) -> Option<Entity<BufferDiff>> {
@@ -2657,7 +2528,6 @@ impl MultiBuffer {
&mut snapshot,
excerpt_edits,
DiffChangeKind::ExpandOrCollapseHunks { expand },
- self.filter_mode,
);
if !edits.is_empty() {
self.subscriptions.publish(edits);
@@ -2745,16 +2615,7 @@ impl MultiBuffer {
drop(cursor);
snapshot.excerpts = new_excerpts;
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| follower.resize_excerpt(id, range, cx));
- }
-
- let edits = Self::sync_diff_transforms(
- &mut snapshot,
- edits,
- DiffChangeKind::BufferEdited,
- self.filter_mode,
- );
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
@@ -2788,7 +2649,7 @@ impl MultiBuffer {
let mut cursor = snapshot
.excerpts
.cursor::<Dimensions<Option<&Locator>, ExcerptOffset>>(());
- let mut excerpt_edits = Vec::<Edit<ExcerptOffset>>::new();
+ let mut edits = Vec::<Edit<ExcerptOffset>>::new();
for locator in &locators {
let prefix = cursor.slice(&Some(locator), Bias::Left);
@@ -2840,15 +2701,15 @@ impl MultiBuffer {
new: new_start_offset..new_start_offset + new_text_len,
};
- if let Some(last_edit) = excerpt_edits.last_mut() {
+ if let Some(last_edit) = edits.last_mut() {
if last_edit.old.end == edit.old.start {
last_edit.old.end = edit.old.end;
last_edit.new.end = edit.new.end;
} else {
- excerpt_edits.push(edit);
+ edits.push(edit);
}
} else {
- excerpt_edits.push(edit);
+ edits.push(edit);
}
new_excerpts.push(excerpt, ());
@@ -2859,22 +2720,12 @@ impl MultiBuffer {
new_excerpts.append(cursor.suffix(), ());
drop(cursor);
- snapshot.excerpts = new_excerpts.clone();
+ snapshot.excerpts = new_excerpts;
- let edits = Self::sync_diff_transforms(
- &mut snapshot,
- excerpt_edits.clone(),
- DiffChangeKind::BufferEdited,
- self.filter_mode,
- );
+ let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.expand_excerpts(ids.clone(), line_count, direction, cx);
- })
- }
cx.emit(Event::Edited {
edited_buffer: None,
});
@@ -2887,11 +2738,10 @@ impl MultiBuffer {
if !changed {
return;
}
- let edits = Self::sync_from_buffer_changes(
+ let edits = Self::sync_(
&mut self.snapshot.borrow_mut(),
&self.buffers,
&self.diffs,
- self.filter_mode,
cx,
);
if !edits.is_empty() {
@@ -2904,24 +2754,17 @@ impl MultiBuffer {
if !changed {
return;
}
- let edits = Self::sync_from_buffer_changes(
- self.snapshot.get_mut(),
- &self.buffers,
- &self.diffs,
- self.filter_mode,
- cx,
- );
+ let edits = Self::sync_(self.snapshot.get_mut(), &self.buffers, &self.diffs, cx);
if !edits.is_empty() {
self.subscriptions.publish(edits);
}
}
- fn sync_from_buffer_changes(
+ fn sync_(
snapshot: &mut MultiBufferSnapshot,
buffers: &HashMap<BufferId, BufferState>,
diffs: &HashMap<BufferId, DiffState>,
- filter_mode: Option<MultiBufferFilterMode>,
cx: &App,
) -> Vec<Edit<MultiBufferOffset>> {
let MultiBufferSnapshot {
@@ -3044,14 +2887,13 @@ impl MultiBuffer {
drop(cursor);
*excerpts = new_excerpts;
- Self::sync_diff_transforms(snapshot, edits, DiffChangeKind::BufferEdited, filter_mode)
+ Self::sync_diff_transforms(snapshot, edits, DiffChangeKind::BufferEdited)
}
fn sync_diff_transforms(
snapshot: &mut MultiBufferSnapshot,
excerpt_edits: Vec<text::Edit<ExcerptOffset>>,
change_kind: DiffChangeKind,
- filter_mode: Option<MultiBufferFilterMode>,
) -> Vec<Edit<MultiBufferOffset>> {
if excerpt_edits.is_empty() {
return vec![];
@@ -3068,8 +2910,8 @@ impl MultiBuffer {
let mut at_transform_boundary = true;
let mut end_of_current_insert = None;
- let mut excerpt_edits: VecDeque<_> = excerpt_edits.into_iter().collect();
- while let Some(edit) = excerpt_edits.pop_front() {
+ let mut excerpt_edits = excerpt_edits.into_iter().peekable();
+ while let Some(edit) = excerpt_edits.next() {
excerpts.seek_forward(&edit.new.start, Bias::Right);
if excerpts.item().is_none() && *excerpts.start() == edit.new.start {
excerpts.prev();
@@ -3090,13 +2932,7 @@ impl MultiBuffer {
}
// Compute the start of the edit in output coordinates.
- let edit_start_overshoot = if let Some(DiffTransform::FilteredInsertedHunk { .. }) =
- old_diff_transforms.item()
- {
- 0
- } else {
- edit.old.start - old_diff_transforms.start().0
- };
+ let edit_start_overshoot = edit.old.start - old_diff_transforms.start().0;
let edit_old_start = old_diff_transforms.start().1 + edit_start_overshoot;
let edit_new_start =
MultiBufferOffset((edit_old_start.0 as isize + output_delta) as usize);
@@ -3110,56 +2946,12 @@ impl MultiBuffer {
&mut old_expanded_hunks,
snapshot,
change_kind,
- filter_mode,
);
- // When the added range of a hunk is edited, the end anchor of the hunk may be moved later
- // in response by hunks_intersecting_range to keep it at a row boundary. In KeepDeletions
- // mode, we need to make sure that the whole added range is still filtered out in this situation.
- // We do that by adding an additional edit that covers the rest of the hunk added range.
- if let Some(current_inserted_hunk) = &end_of_current_insert
- && current_inserted_hunk.is_filtered
- // No additional edit needed if we've already covered the whole added range.
- && current_inserted_hunk.insertion_end_offset > edit.new.end
- // No additional edit needed if this edit just touched the start of the hunk
- // (this also prevents pushing the deleted region for the hunk twice).
- && edit.new.end > current_inserted_hunk.hunk_excerpt_start
- // No additional edit needed if there is a subsequent edit that intersects
- // the same hunk (the last such edit will take care of it).
- && excerpt_edits.front().is_none_or(|next_edit| {
- next_edit.new.start >= current_inserted_hunk.insertion_end_offset
- })
- {
- let overshoot = current_inserted_hunk.insertion_end_offset - edit.new.end;
- let additional_edit = Edit {
- old: edit.old.end..edit.old.end + overshoot,
- new: edit.new.end..current_inserted_hunk.insertion_end_offset,
- };
- excerpt_edits.push_front(additional_edit);
- }
-
// Compute the end of the edit in output coordinates.
- let edit_old_end_overshoot = if let Some(DiffTransform::FilteredInsertedHunk {
- ..
- }) = old_diff_transforms.item()
- {
- ExcerptDimension(MultiBufferOffset(0))
- } else {
- ExcerptDimension(MultiBufferOffset(
- edit.old.end - old_diff_transforms.start().0,
- ))
- };
- let edit_new_end_overshoot = if let Some(current_inserted_hunk) = &end_of_current_insert
- && current_inserted_hunk.is_filtered
- {
- let insertion_end_offset = current_inserted_hunk.insertion_end_offset;
- let excerpt_len = new_diff_transforms.summary().excerpt_len();
- let base = insertion_end_offset.max(excerpt_len);
- edit.new.end.saturating_sub(base)
- } else {
- edit.new.end - new_diff_transforms.summary().excerpt_len()
- };
- let edit_old_end = old_diff_transforms.start().1 + edit_old_end_overshoot.0;
+ let edit_old_end_overshoot = edit.old.end - old_diff_transforms.start().0;
+ let edit_new_end_overshoot = edit.new.end - new_diff_transforms.summary().excerpt_len();
+ let edit_old_end = old_diff_transforms.start().1 + edit_old_end_overshoot;
let edit_new_end = new_diff_transforms.summary().output.len + edit_new_end_overshoot;
let output_edit = Edit {
old: edit_old_start..edit_old_end,
@@ -3176,16 +2968,16 @@ impl MultiBuffer {
// then recreate the content up to the end of this transform, to prepare
// for reusing additional slices of the old transforms.
if excerpt_edits
- .front()
+ .peek()
.is_none_or(|next_edit| next_edit.old.start >= old_diff_transforms.end().0)
{
let keep_next_old_transform = (old_diff_transforms.start().0 >= edit.old.end)
&& match old_diff_transforms.item() {
- Some(
- DiffTransform::InsertedHunk { hunk_info, .. }
- | DiffTransform::FilteredInsertedHunk { hunk_info, .. },
- ) => excerpts.item().is_some_and(|excerpt| {
- hunk_info.hunk_start_anchor.is_valid(&excerpt.buffer)
+ Some(DiffTransform::BufferContent {
+ inserted_hunk_info: Some(hunk),
+ ..
+ }) => excerpts.item().is_some_and(|excerpt| {
+ hunk.hunk_start_anchor.is_valid(&excerpt.buffer)
}),
_ => true,
};
@@ -3201,7 +2993,7 @@ impl MultiBuffer {
snapshot,
&mut new_diff_transforms,
excerpt_offset,
- end_of_current_insert.as_ref(),
+ end_of_current_insert,
);
at_transform_boundary = true;
}
@@ -3213,8 +3005,9 @@ impl MultiBuffer {
// Ensure there's always at least one buffer content transform.
if new_diff_transforms.is_empty() {
new_diff_transforms.push(
- DiffTransform::Unmodified {
+ DiffTransform::BufferContent {
summary: Default::default(),
+ inserted_hunk_info: None,
},
(),
);
@@ -3238,11 +3031,10 @@ impl MultiBuffer {
Dimensions<ExcerptOffset, MultiBufferOffset>,
>,
new_diff_transforms: &mut SumTree<DiffTransform>,
- end_of_current_insert: &mut Option<CurrentInsertedHunk>,
+ end_of_current_insert: &mut Option<(ExcerptOffset, DiffTransformHunkInfo)>,
old_expanded_hunks: &mut HashSet<DiffTransformHunkInfo>,
snapshot: &MultiBufferSnapshot,
change_kind: DiffChangeKind,
- filter_mode: Option<MultiBufferFilterMode>,
) -> bool {
log::trace!(
"recomputing diff transform for edit {:?} => {:?}",
@@ -3308,7 +3100,6 @@ impl MultiBuffer {
excerpt_id: excerpt.id,
hunk_start_anchor: hunk.buffer_range.start,
hunk_secondary_status: hunk.secondary_status,
- base_text_byte_range: hunk.diff_base_byte_range.clone(),
};
let hunk_excerpt_start = excerpt_start
@@ -3320,7 +3111,7 @@ impl MultiBuffer {
snapshot,
new_diff_transforms,
hunk_excerpt_start,
- end_of_current_insert.as_ref(),
+ *end_of_current_insert,
);
// For every existing hunk, determine if it was previously expanded
@@ -3353,7 +3144,6 @@ impl MultiBuffer {
if !hunk.diff_base_byte_range.is_empty()
&& hunk_buffer_range.start >= edit_buffer_start
&& hunk_buffer_range.start <= excerpt_buffer_end
- && filter_mode != Some(MultiBufferFilterMode::KeepInsertions)
{
let base_text = diff.base_text();
let mut text_cursor =
@@ -3369,9 +3159,10 @@ impl MultiBuffer {
new_diff_transforms.push(
DiffTransform::DeletedHunk {
+ base_text_byte_range: hunk.diff_base_byte_range.clone(),
summary: base_text_summary,
buffer_id: excerpt.buffer_id,
- hunk_info: hunk_info.clone(),
+ hunk_info,
has_trailing_newline,
},
(),
@@ -3379,15 +3170,8 @@ impl MultiBuffer {
}
if !hunk_buffer_range.is_empty() {
- let is_filtered =
- filter_mode == Some(MultiBufferFilterMode::KeepDeletions);
- let insertion_end_offset = hunk_excerpt_end.min(excerpt_end);
- *end_of_current_insert = Some(CurrentInsertedHunk {
- hunk_excerpt_start,
- insertion_end_offset,
- hunk_info,
- is_filtered,
- });
+ *end_of_current_insert =
+ Some((hunk_excerpt_end.min(excerpt_end), hunk_info));
}
}
}
@@ -3407,8 +3191,15 @@ impl MultiBuffer {
new_transforms: &mut SumTree<DiffTransform>,
subtree: SumTree<DiffTransform>,
) {
- if let Some(transform) = subtree.first()
- && Self::extend_last_buffer_content_transform(new_transforms, transform)
+ if let Some(DiffTransform::BufferContent {
+ inserted_hunk_info,
+ summary,
+ }) = subtree.first()
+ && Self::extend_last_buffer_content_transform(
+ new_transforms,
+ *inserted_hunk_info,
+ *summary,
+ )
{
let mut cursor = subtree.cursor::<()>(());
cursor.next();
@@ -3420,7 +3211,16 @@ impl MultiBuffer {
}
fn push_diff_transform(new_transforms: &mut SumTree<DiffTransform>, transform: DiffTransform) {
- if Self::extend_last_buffer_content_transform(new_transforms, &transform) {
+ if let DiffTransform::BufferContent {
+ inserted_hunk_info: inserted_hunk_anchor,
+ summary,
+ } = transform
+ && Self::extend_last_buffer_content_transform(
+ new_transforms,
+ inserted_hunk_anchor,
+ summary,
+ )
+ {
return;
}
new_transforms.push(transform, ());
@@ -3430,56 +3230,55 @@ impl MultiBuffer {
old_snapshot: &MultiBufferSnapshot,
new_transforms: &mut SumTree<DiffTransform>,
end_offset: ExcerptOffset,
- current_inserted_hunk: Option<&CurrentInsertedHunk>,
+ current_inserted_hunk: Option<(ExcerptOffset, DiffTransformHunkInfo)>,
) {
- if let Some(current_inserted_hunk) = current_inserted_hunk {
- let start_offset = new_transforms.summary().excerpt_len();
- let end_offset = current_inserted_hunk.insertion_end_offset.min(end_offset);
- if end_offset > start_offset {
- let summary_to_add = old_snapshot
- .text_summary_for_excerpt_offset_range::<MBTextSummary>(
- start_offset..end_offset,
- );
+ let inserted_region = current_inserted_hunk.map(|(insertion_end_offset, hunk_info)| {
+ (end_offset.min(insertion_end_offset), Some(hunk_info))
+ });
+ let unchanged_region = [(end_offset, None)];
- let transform = if current_inserted_hunk.is_filtered {
- DiffTransform::FilteredInsertedHunk {
- summary: summary_to_add,
- hunk_info: current_inserted_hunk.hunk_info.clone(),
- }
- } else {
- DiffTransform::InsertedHunk {
- summary: summary_to_add,
- hunk_info: current_inserted_hunk.hunk_info.clone(),
- }
- };
- if !Self::extend_last_buffer_content_transform(new_transforms, &transform) {
- new_transforms.push(transform, ())
- }
+ for (end_offset, inserted_hunk_info) in inserted_region.into_iter().chain(unchanged_region)
+ {
+ let start_offset = new_transforms.summary().excerpt_len();
+ if end_offset <= start_offset {
+ continue;
}
- }
-
- let start_offset = new_transforms.summary().excerpt_len();
- if end_offset > start_offset {
let summary_to_add = old_snapshot
.text_summary_for_excerpt_offset_range::<MBTextSummary>(start_offset..end_offset);
- let transform = DiffTransform::Unmodified {
- summary: summary_to_add,
- };
- if !Self::extend_last_buffer_content_transform(new_transforms, &transform) {
- new_transforms.push(transform, ())
+ if !Self::extend_last_buffer_content_transform(
+ new_transforms,
+ inserted_hunk_info,
+ summary_to_add,
+ ) {
+ new_transforms.push(
+ DiffTransform::BufferContent {
+ summary: summary_to_add,
+ inserted_hunk_info,
+ },
+ (),
+ )
}
}
}
fn extend_last_buffer_content_transform(
new_transforms: &mut SumTree<DiffTransform>,
- transform: &DiffTransform,
+ new_inserted_hunk_info: Option<DiffTransformHunkInfo>,
+ summary_to_add: MBTextSummary,
) -> bool {
let mut did_extend = false;
new_transforms.update_last(
|last_transform| {
- did_extend = last_transform.merge_with(&transform);
+ if let DiffTransform::BufferContent {
+ summary,
+ inserted_hunk_info: inserted_hunk_anchor,
+ } = last_transform
+ && *inserted_hunk_anchor == new_inserted_hunk_info
+ {
+ *summary += summary_to_add;
+ did_extend = true;
+ }
},
(),
);
@@ -3487,72 +3286,6 @@ impl MultiBuffer {
}
}
-impl DiffTransform {
- /// Ergonomic wrapper for [`DiffTransform::merged_with`] that applies the
- /// merging in-place. Returns `true` if merging was possible.
- #[must_use = "check whether merging actually succeeded"]
- fn merge_with(&mut self, other: &Self) -> bool {
- match self.to_owned().merged_with(other) {
- Some(merged) => {
- *self = merged;
- true
- }
- None => false,
- }
- }
-
- /// Attempt to merge `self` with `other`, and return the merged transform.
- ///
- /// This will succeed if all of the following are true:
- /// - both transforms are the same variant
- /// - neither transform is [`DiffTransform::DeletedHunk`]
- /// - if both transform are either [`DiffTransform::InsertedHunk`] or
- /// [`DiffTransform::FilteredInsertedHunk`], then their
- /// `hunk_info.hunk_start_anchor`s match
- #[must_use = "check whether merging actually succeeded"]
- #[rustfmt::skip]
- fn merged_with(self, other: &Self) -> Option<Self> {
- match (self, other) {
- (
- DiffTransform::Unmodified { mut summary },
- DiffTransform::Unmodified { summary: other_summary },
- ) => {
- summary += *other_summary;
- Some(DiffTransform::Unmodified { summary })
- }
- (
- DiffTransform::FilteredInsertedHunk { mut summary, hunk_info },
- DiffTransform::FilteredInsertedHunk {
- hunk_info: other_hunk_info,
- summary: other_summary,
- },
- ) => {
- if hunk_info.hunk_start_anchor == other_hunk_info.hunk_start_anchor {
- summary += *other_summary;
- Some(DiffTransform::FilteredInsertedHunk { summary, hunk_info })
- } else {
- None
- }
- }
- (
- DiffTransform::InsertedHunk { mut summary, hunk_info },
- DiffTransform::InsertedHunk {
- hunk_info: other_hunk_info,
- summary: other_summary,
- },
- ) => {
- if hunk_info.hunk_start_anchor == other_hunk_info.hunk_start_anchor {
- summary += *other_summary;
- Some(DiffTransform::InsertedHunk { summary, hunk_info })
- } else {
- None
- }
- }
- _ => return None,
- }
- }
-}
-
fn build_excerpt_ranges(
ranges: impl IntoIterator<Item = Range<Point>>,
context_line_count: u32,
@@ -3875,31 +3608,11 @@ impl MultiBufferSnapshot {
} else {
range.end.row + 1
};
-
- let word_diffs = (!hunk.base_word_diffs.is_empty()
- || !hunk.buffer_word_diffs.is_empty())
- .then(|| {
- let hunk_start_offset =
- Anchor::in_buffer(excerpt.id, hunk.buffer_range.start).to_offset(self);
-
- hunk.base_word_diffs
- .iter()
- .map(|diff| hunk_start_offset + diff.start..hunk_start_offset + diff.end)
- .chain(
- hunk.buffer_word_diffs
- .into_iter()
- .map(|diff| Anchor::range_in_buffer(excerpt.id, diff).to_offset(self)),
- )
- .collect()
- })
- .unwrap_or_default();
-
Some(MultiBufferDiffHunk {
row_range: MultiBufferRow(range.start.row)..MultiBufferRow(end_row),
buffer_id: excerpt.buffer_id,
excerpt_id: excerpt.id,
buffer_range: hunk.buffer_range.clone(),
- word_diffs,
diff_base_byte_range: BufferOffset(hunk.diff_base_byte_range.start)
..BufferOffset(hunk.diff_base_byte_range.end),
secondary_status: hunk.secondary_status,
@@ -4804,20 +4517,19 @@ impl MultiBufferSnapshot {
let end_overshoot = std::cmp::min(range.end, diff_transform_end) - diff_transform_start;
let mut result = match first_transform {
- DiffTransform::Unmodified { .. } | DiffTransform::InsertedHunk { .. } => {
+ DiffTransform::BufferContent { .. } => {
let excerpt_start = cursor.start().1 + start_overshoot;
let excerpt_end = cursor.start().1 + end_overshoot;
self.text_summary_for_excerpt_offset_range(excerpt_start..excerpt_end)
}
- DiffTransform::FilteredInsertedHunk { .. } => MBD::default(),
DiffTransform::DeletedHunk {
buffer_id,
+ base_text_byte_range,
has_trailing_newline,
- hunk_info,
..
} => {
- let buffer_start = hunk_info.base_text_byte_range.start + start_overshoot;
- let mut buffer_end = hunk_info.base_text_byte_range.start + end_overshoot;
+ let buffer_start = base_text_byte_range.start + start_overshoot;
+ let mut buffer_end = base_text_byte_range.start + end_overshoot;
let Some(base_text) = self.diffs.get(buffer_id).map(|diff| diff.base_text()) else {
panic!("{:?} is in non-existent deleted hunk", range.start)
};
@@ -4859,26 +4571,25 @@ impl MultiBufferSnapshot {
let overshoot = range.end - cursor.start().0;
let suffix = match last_transform {
- DiffTransform::Unmodified { .. } | DiffTransform::InsertedHunk { .. } => {
+ DiffTransform::BufferContent { .. } => {
let end = cursor.start().1 + overshoot;
self.text_summary_for_excerpt_offset_range::<MBD>(cursor.start().1..end)
}
- DiffTransform::FilteredInsertedHunk { .. } => MBD::default(),
DiffTransform::DeletedHunk {
+ base_text_byte_range,
buffer_id,
has_trailing_newline,
- hunk_info,
..
} => {
- let buffer_end = hunk_info.base_text_byte_range.start + overshoot;
+ let buffer_end = base_text_byte_range.start + overshoot;
let Some(base_text) = self.diffs.get(buffer_id).map(|diff| diff.base_text()) else {
panic!("{:?} is in non-existent deleted hunk", range.end)
};
let mut suffix = base_text.text_summary_for_range::<MBD::TextDimension, _>(
- hunk_info.base_text_byte_range.start..buffer_end,
+ base_text_byte_range.start..buffer_end,
);
- if *has_trailing_newline && buffer_end == hunk_info.base_text_byte_range.end + 1 {
+ if *has_trailing_newline && buffer_end == base_text_byte_range.end + 1 {
suffix.add_assign(&<MBD::TextDimension>::from_text_summary(
&TextSummary::from("\n"),
))
@@ -4984,7 +4695,7 @@ impl MultiBufferSnapshot {
match diff_transforms.item() {
Some(DiffTransform::DeletedHunk {
buffer_id,
- hunk_info,
+ base_text_byte_range,
..
}) => {
if let Some(diff_base_anchor) = &anchor.diff_base_anchor
@@ -4993,12 +4704,12 @@ impl MultiBufferSnapshot {
&& base_text.can_resolve(diff_base_anchor)
{
let base_text_offset = diff_base_anchor.to_offset(base_text);
- if base_text_offset >= hunk_info.base_text_byte_range.start
- && base_text_offset <= hunk_info.base_text_byte_range.end
+ if base_text_offset >= base_text_byte_range.start
+ && base_text_offset <= base_text_byte_range.end
{
let position_in_hunk = base_text
.text_summary_for_range::<MBD::TextDimension, _>(
- hunk_info.base_text_byte_range.start..base_text_offset,
+ base_text_byte_range.start..base_text_offset,
);
position.0.add_text_dim(&position_in_hunk);
} else if at_transform_end {
@@ -5012,14 +4723,8 @@ impl MultiBufferSnapshot {
diff_transforms.next();
continue;
}
-
- if !matches!(
- diff_transforms.item(),
- Some(DiffTransform::FilteredInsertedHunk { .. })
- ) {
- let overshoot = excerpt_position - diff_transforms.start().0;
- position += overshoot;
- }
+ let overshoot = excerpt_position - diff_transforms.start().0;
+ position += overshoot;
}
}
@@ -5309,12 +5014,11 @@ impl MultiBufferSnapshot {
let mut diff_base_anchor = None;
if let Some(DiffTransform::DeletedHunk {
buffer_id,
+ base_text_byte_range,
has_trailing_newline,
- hunk_info,
..
}) = diff_transforms.item()
{
- let base_text_byte_range = &hunk_info.base_text_byte_range;
let diff = self.diffs.get(buffer_id).expect("missing diff");
if offset_in_transform > base_text_byte_range.len() {
debug_assert!(*has_trailing_newline);