@@ -503,14 +503,37 @@ impl DisplayMap {
};
assert_eq!(self.entity_id, companion.read(cx).rhs_display_map_id);
- let snapshot = self.unfold_intersecting([Anchor::min()..Anchor::max()], true, cx);
+ // 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();
+ let snapshot = {
+ let edits = self.buffer_subscription.consume();
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let tab_size = Self::tab_size(&self.buffer, cx);
+ let (snapshot, edits) = self.inlay_map.sync(snapshot, edits.into_inner());
+ let (mut writer, snapshot, edits) = self.fold_map.write(snapshot, edits);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
+ let (_snapshot, _edits) = self
+ .wrap_map
+ .update(cx, |wrap_map, cx| wrap_map.sync(snapshot, edits, cx));
+
+ let (snapshot, edits) =
+ writer.unfold_intersecting([Anchor::min()..Anchor::max()], true);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
+ let (snapshot, _edits) = self
+ .wrap_map
+ .update(cx, |wrap_map, cx| wrap_map.sync(snapshot, edits, cx));
+
+ self.block_map
+ .retain_blocks_raw(|block| !matches!(block.placement, BlockPlacement::Replace(_)));
+ snapshot
+ };
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)..snapshot.max_point().row(),
+ old: WrapRow(0)..old_max_row,
new: WrapRow(0)..snapshot.max_point().row(),
}]
.into_iter()
@@ -707,6 +707,7 @@ impl BlockMap {
}
}
+ // Warning: doesn't sync the block map, use advisedly
pub(crate) fn insert_block_raw(
&mut self,
block: BlockProperties<Anchor>,
@@ -732,6 +733,20 @@ impl BlockMap {
id
}
+ // Warning: doesn't sync the block map, use advisedly
+ pub(crate) fn retain_blocks_raw(&mut self, mut pred: impl FnMut(&Arc<CustomBlock>) -> bool) {
+ let mut ids_to_remove = HashSet::default();
+ self.custom_blocks.retain(|block| {
+ let keep = pred(block);
+ if !keep {
+ ids_to_remove.insert(block.id);
+ }
+ keep
+ });
+ self.custom_blocks_by_id
+ .retain(|id, _| !ids_to_remove.contains(id));
+ }
+
#[ztracing::instrument(skip_all, fields(edits = ?edits))]
fn sync(
&self,
@@ -2090,9 +2090,12 @@ mod tests {
use workspace::Workspace;
use crate::SplittableEditor;
- use crate::display_map::{BlockPlacement, BlockProperties, BlockStyle};
+ use crate::display_map::{
+ BlockPlacement, BlockProperties, BlockStyle, Crease, FoldPlaceholder,
+ };
use crate::inlays::Inlay;
use crate::test::{editor_content_with_blocks_and_width, set_block_content_for_tests};
+ use multi_buffer::MultiBufferOffset;
async fn init_test(
cx: &mut gpui::TestAppContext,
@@ -5452,6 +5455,95 @@ mod tests {
);
}
+ #[gpui::test]
+ async fn test_range_folds_removed_on_split(cx: &mut gpui::TestAppContext) {
+ use rope::Point;
+ use unindent::Unindent as _;
+
+ let (editor, mut cx) = init_test(cx, SoftWrap::None, DiffViewStyle::Unified).await;
+
+ let base_text = "
+ aaa
+ bbb
+ ccc
+ ddd
+ eee"
+ .unindent();
+ let current_text = "
+ aaa
+ bbb
+ ccc
+ ddd
+ eee"
+ .unindent();
+
+ let (buffer, diff) = buffer_with_diff(&base_text, ¤t_text, &mut cx);
+
+ editor.update(cx, |editor, cx| {
+ let path = PathKey::for_buffer(&buffer, cx);
+ editor.set_excerpts_for_path(
+ path,
+ buffer.clone(),
+ vec![Point::new(0, 0)..buffer.read(cx).max_point()],
+ 0,
+ diff.clone(),
+ cx,
+ );
+ });
+
+ cx.run_until_parked();
+
+ editor.update_in(cx, |editor, window, cx| {
+ editor.rhs_editor.update(cx, |rhs_editor, cx| {
+ rhs_editor.fold_creases(
+ vec![Crease::simple(
+ Point::new(1, 0)..Point::new(3, 0),
+ FoldPlaceholder::test(),
+ )],
+ false,
+ window,
+ cx,
+ );
+ });
+ });
+
+ cx.run_until_parked();
+
+ editor.update_in(cx, |editor, window, cx| {
+ editor.split(window, cx);
+ });
+
+ cx.run_until_parked();
+
+ let (rhs_editor, lhs_editor) = editor.read_with(cx, |editor, _cx| {
+ (
+ editor.rhs_editor.clone(),
+ editor.lhs.as_ref().unwrap().editor.clone(),
+ )
+ });
+
+ let rhs_has_folds_after_split = rhs_editor.update(cx, |editor, cx| {
+ let snapshot = editor.display_snapshot(cx);
+ snapshot
+ .folds_in_range(MultiBufferOffset(0)..snapshot.buffer_snapshot().len())
+ .next()
+ .is_some()
+ });
+ assert!(
+ !rhs_has_folds_after_split,
+ "rhs should not have range folds after split"
+ );
+
+ let lhs_has_folds = lhs_editor.update(cx, |editor, cx| {
+ let snapshot = editor.display_snapshot(cx);
+ snapshot
+ .folds_in_range(MultiBufferOffset(0)..snapshot.buffer_snapshot().len())
+ .next()
+ .is_some()
+ });
+ assert!(!lhs_has_folds, "lhs should not have any range folds");
+ }
+
#[gpui::test]
async fn test_multiline_inlays_create_spacers(cx: &mut gpui::TestAppContext) {
use rope::Point;