diff --git a/crates/buffer_diff/src/buffer_diff.rs b/crates/buffer_diff/src/buffer_diff.rs index 6060b9a6958a3a802945ab9dcfd59ec80262665c..3092373b5f36507bc0cd993e2ef807556b960050 100644 --- a/crates/buffer_diff/src/buffer_diff.rs +++ b/crates/buffer_diff/src/buffer_diff.rs @@ -193,10 +193,6 @@ impl std::fmt::Debug for BufferDiffInner { } impl BufferDiffSnapshot { - pub fn buffer_diff_id(&self) -> BufferId { - self.inner.base_text.remote_id() - } - #[cfg(test)] fn new_sync( buffer: text::BufferSnapshot, @@ -289,16 +285,22 @@ impl BufferDiffSnapshot { &self.inner.base_text } - pub fn base_texts_eq(&self, other: &Self) -> bool { + /// If this function returns `true`, the base texts are equal. If this + /// function returns `false`, they might be equal, but might not. This + /// result is used to avoid recalculating diffs in situations where we know + /// nothing has changed. + /// + /// todo! better name + pub fn base_texts_definitely_eq(&self, other: &Self) -> bool { if self.inner.base_text_exists != other.inner.base_text_exists { return false; } let left = &self.inner.base_text; let right = &other.inner.base_text; - // FIXME this is wrong - let (old_id, old_empty) = (left.remote_id(), left.is_empty()); - let (new_id, new_empty) = (right.remote_id(), right.is_empty()); - new_id == old_id || (new_empty && old_empty) + let (old_id, old_version, old_empty) = (left.remote_id(), left.version(), left.is_empty()); + let (new_id, new_version, new_empty) = + (right.remote_id(), right.version(), right.is_empty()); + (new_id == old_id && new_version == old_version) || (new_empty && old_empty) } pub fn row_to_base_text_row(&self, row: BufferRow, buffer: &text::BufferSnapshot) -> u32 { @@ -1106,7 +1108,6 @@ impl BufferDiff { None, cx, )); - // FIXME this.set_snapshot(inner, &buffer, true, cx); this } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 9421d22695096c547fd6ea225d02a24cc5b5b2fb..4be66514d1729ac2b387538dd6b08db72c427398 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -28381,208 +28381,6 @@ async fn test_multibuffer_selections_with_folding(cx: &mut TestAppContext) { "}); } -// FIXME restore these tests in some form -// #[gpui::test] -// async fn test_filtered_editor_pair(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let mut leader_cx = EditorTestContext::new(cx).await; - -// let diff_base = indoc!( -// r#" -// one -// two -// three -// four -// five -// six -// "# -// ); - -// let initial_state = indoc!( -// r#" -// ˇone -// two -// THREE -// four -// five -// six -// "# -// ); - -// leader_cx.set_state(initial_state); - -// leader_cx.set_head_text(&diff_base); -// leader_cx.run_until_parked(); - -// let follower = leader_cx.update_multibuffer(|leader, cx| { -// leader.set_filter_mode(Some(MultiBufferFilterMode::KeepInsertions)); -// leader.set_all_diff_hunks_expanded(cx); -// leader.get_or_create_follower(cx) -// }); -// follower.update(cx, |follower, cx| { -// follower.set_filter_mode(Some(MultiBufferFilterMode::KeepDeletions)); -// follower.set_all_diff_hunks_expanded(cx); -// }); - -// let follower_editor = -// leader_cx.new_window_entity(|window, cx| build_editor(follower, window, cx)); -// // leader_cx.window.focus(&follower_editor.focus_handle(cx)); - -// let mut follower_cx = EditorTestContext::for_editor_in(follower_editor, &mut leader_cx).await; -// cx.run_until_parked(); - -// leader_cx.assert_editor_state(initial_state); -// follower_cx.assert_editor_state(indoc! { -// r#" -// ˇone -// two -// three -// four -// five -// six -// "# -// }); - -// follower_cx.editor(|editor, _window, cx| { -// assert!(editor.read_only(cx)); -// }); - -// leader_cx.update_editor(|editor, _window, cx| { -// editor.edit([(Point::new(4, 0)..Point::new(5, 0), "FIVE\n")], cx); -// }); -// cx.run_until_parked(); - -// leader_cx.assert_editor_state(indoc! { -// r#" -// ˇone -// two -// THREE -// four -// FIVE -// six -// "# -// }); - -// follower_cx.assert_editor_state(indoc! { -// r#" -// ˇone -// two -// three -// four -// five -// six -// "# -// }); - -// leader_cx.update_editor(|editor, _window, cx| { -// editor.edit([(Point::new(6, 0)..Point::new(6, 0), "SEVEN")], cx); -// }); -// cx.run_until_parked(); - -// leader_cx.assert_editor_state(indoc! { -// r#" -// ˇone -// two -// THREE -// four -// FIVE -// six -// SEVEN"# -// }); - -// follower_cx.assert_editor_state(indoc! { -// r#" -// ˇone -// two -// three -// four -// five -// six -// "# -// }); - -// leader_cx.update_editor(|editor, window, cx| { -// editor.move_down(&MoveDown, window, cx); -// editor.refresh_selected_text_highlights(true, window, cx); -// }); -// leader_cx.run_until_parked(); -// } - -// #[gpui::test] -// async fn test_filtered_editor_pair_complex(cx: &mut gpui::TestAppContext) { -// init_test(cx, |_| {}); -// let base_text = "base\n"; -// let buffer_text = "buffer\n"; - -// let buffer1 = cx.new(|cx| Buffer::local(buffer_text, cx)); -// let diff1 = cx.new(|cx| BufferDiff::new_with_base_text(base_text, &buffer1, cx)); - -// let extra_buffer_1 = cx.new(|cx| Buffer::local("dummy text 1\n", cx)); -// let extra_diff_1 = cx.new(|cx| BufferDiff::new_with_base_text("", &extra_buffer_1, cx)); -// let extra_buffer_2 = cx.new(|cx| Buffer::local("dummy text 2\n", cx)); -// let extra_diff_2 = cx.new(|cx| BufferDiff::new_with_base_text("", &extra_buffer_2, cx)); - -// let leader = cx.new(|cx| { -// let mut leader = MultiBuffer::new(Capability::ReadWrite); -// leader.set_all_diff_hunks_expanded(cx); -// leader.set_filter_mode(Some(MultiBufferFilterMode::KeepInsertions)); -// leader -// }); -// let follower = leader.update(cx, |leader, cx| leader.get_or_create_follower(cx)); -// follower.update(cx, |follower, _| { -// follower.set_filter_mode(Some(MultiBufferFilterMode::KeepDeletions)); -// }); - -// leader.update(cx, |leader, cx| { -// leader.insert_excerpts_after( -// ExcerptId::min(), -// extra_buffer_2.clone(), -// vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], -// cx, -// ); -// leader.add_diff(extra_diff_2.clone(), cx); - -// leader.insert_excerpts_after( -// ExcerptId::min(), -// extra_buffer_1.clone(), -// vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], -// cx, -// ); -// leader.add_diff(extra_diff_1.clone(), cx); - -// leader.insert_excerpts_after( -// ExcerptId::min(), -// buffer1.clone(), -// vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], -// cx, -// ); -// leader.add_diff(diff1.clone(), cx); -// }); - -// cx.run_until_parked(); -// let mut cx = cx.add_empty_window(); - -// let leader_editor = cx -// .new_window_entity(|window, cx| Editor::for_multibuffer(leader.clone(), None, window, cx)); -// let follower_editor = cx.new_window_entity(|window, cx| { -// Editor::for_multibuffer(follower.clone(), None, window, cx) -// }); - -// let mut leader_cx = EditorTestContext::for_editor_in(leader_editor.clone(), &mut cx).await; -// leader_cx.assert_editor_state(indoc! {" -// ˇbuffer - -// dummy text 1 - -// dummy text 2 -// "}); -// let mut follower_cx = EditorTestContext::for_editor_in(follower_editor.clone(), &mut cx).await; -// follower_cx.assert_editor_state(indoc! {" -// ˇbase - -// "}); -// } - #[gpui::test] async fn test_multibuffer_scroll_cursor_top_margin(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/split.rs b/crates/editor/src/split.rs index f0d442f328b131e459fb982ae483079664dc5e0c..3841e4656415effaa5aa8043a6c8be1f87d12502 100644 --- a/crates/editor/src/split.rs +++ b/crates/editor/src/split.rs @@ -410,4 +410,206 @@ mod tests { SplittableEditor::new_unsplit(multibuffer, project, workspace, window, cx) }); } + + // FIXME restore these tests in some form + // #[gpui::test] + // async fn test_filtered_editor_pair(cx: &mut gpui::TestAppContext) { + // init_test(cx, |_| {}); + // let mut leader_cx = EditorTestContext::new(cx).await; + + // let diff_base = indoc!( + // r#" + // one + // two + // three + // four + // five + // six + // "# + // ); + + // let initial_state = indoc!( + // r#" + // ˇone + // two + // THREE + // four + // five + // six + // "# + // ); + + // leader_cx.set_state(initial_state); + + // leader_cx.set_head_text(&diff_base); + // leader_cx.run_until_parked(); + + // let follower = leader_cx.update_multibuffer(|leader, cx| { + // leader.set_filter_mode(Some(MultiBufferFilterMode::KeepInsertions)); + // leader.set_all_diff_hunks_expanded(cx); + // leader.get_or_create_follower(cx) + // }); + // follower.update(cx, |follower, cx| { + // follower.set_filter_mode(Some(MultiBufferFilterMode::KeepDeletions)); + // follower.set_all_diff_hunks_expanded(cx); + // }); + + // let follower_editor = + // leader_cx.new_window_entity(|window, cx| build_editor(follower, window, cx)); + // // leader_cx.window.focus(&follower_editor.focus_handle(cx)); + + // let mut follower_cx = EditorTestContext::for_editor_in(follower_editor, &mut leader_cx).await; + // cx.run_until_parked(); + + // leader_cx.assert_editor_state(initial_state); + // follower_cx.assert_editor_state(indoc! { + // r#" + // ˇone + // two + // three + // four + // five + // six + // "# + // }); + + // follower_cx.editor(|editor, _window, cx| { + // assert!(editor.read_only(cx)); + // }); + + // leader_cx.update_editor(|editor, _window, cx| { + // editor.edit([(Point::new(4, 0)..Point::new(5, 0), "FIVE\n")], cx); + // }); + // cx.run_until_parked(); + + // leader_cx.assert_editor_state(indoc! { + // r#" + // ˇone + // two + // THREE + // four + // FIVE + // six + // "# + // }); + + // follower_cx.assert_editor_state(indoc! { + // r#" + // ˇone + // two + // three + // four + // five + // six + // "# + // }); + + // leader_cx.update_editor(|editor, _window, cx| { + // editor.edit([(Point::new(6, 0)..Point::new(6, 0), "SEVEN")], cx); + // }); + // cx.run_until_parked(); + + // leader_cx.assert_editor_state(indoc! { + // r#" + // ˇone + // two + // THREE + // four + // FIVE + // six + // SEVEN"# + // }); + + // follower_cx.assert_editor_state(indoc! { + // r#" + // ˇone + // two + // three + // four + // five + // six + // "# + // }); + + // leader_cx.update_editor(|editor, window, cx| { + // editor.move_down(&MoveDown, window, cx); + // editor.refresh_selected_text_highlights(true, window, cx); + // }); + // leader_cx.run_until_parked(); + // } + + // #[gpui::test] + // async fn test_filtered_editor_pair_complex(cx: &mut gpui::TestAppContext) { + // init_test(cx, |_| {}); + // let base_text = "base\n"; + // let buffer_text = "buffer\n"; + + // let buffer1 = cx.new(|cx| Buffer::local(buffer_text, cx)); + // let diff1 = cx.new(|cx| BufferDiff::new_with_base_text(base_text, &buffer1, cx)); + + // let extra_buffer_1 = cx.new(|cx| Buffer::local("dummy text 1\n", cx)); + // let extra_diff_1 = cx.new(|cx| BufferDiff::new_with_base_text("", &extra_buffer_1, cx)); + // let extra_buffer_2 = cx.new(|cx| Buffer::local("dummy text 2\n", cx)); + // let extra_diff_2 = cx.new(|cx| BufferDiff::new_with_base_text("", &extra_buffer_2, cx)); + + // let leader = cx.new(|cx| { + // let mut leader = MultiBuffer::new(Capability::ReadWrite); + // leader.set_all_diff_hunks_expanded(cx); + // leader.set_filter_mode(Some(MultiBufferFilterMode::KeepInsertions)); + // leader + // }); + // let follower = leader.update(cx, |leader, cx| leader.get_or_create_follower(cx)); + // follower.update(cx, |follower, _| { + // follower.set_filter_mode(Some(MultiBufferFilterMode::KeepDeletions)); + // }); + + // leader.update(cx, |leader, cx| { + // leader.insert_excerpts_after( + // ExcerptId::min(), + // extra_buffer_2.clone(), + // vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], + // cx, + // ); + // leader.add_diff(extra_diff_2.clone(), cx); + + // leader.insert_excerpts_after( + // ExcerptId::min(), + // extra_buffer_1.clone(), + // vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], + // cx, + // ); + // leader.add_diff(extra_diff_1.clone(), cx); + + // leader.insert_excerpts_after( + // ExcerptId::min(), + // buffer1.clone(), + // vec![ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], + // cx, + // ); + // leader.add_diff(diff1.clone(), cx); + // }); + + // cx.run_until_parked(); + // let mut cx = cx.add_empty_window(); + + // let leader_editor = cx + // .new_window_entity(|window, cx| Editor::for_multibuffer(leader.clone(), None, window, cx)); + // let follower_editor = cx.new_window_entity(|window, cx| { + // Editor::for_multibuffer(follower.clone(), None, window, cx) + // }); + + // let mut leader_cx = EditorTestContext::for_editor_in(leader_editor.clone(), &mut cx).await; + // leader_cx.assert_editor_state(indoc! {" + // ˇbuffer + + // dummy text 1 + + // dummy text 2 + // "}); + // let mut follower_cx = EditorTestContext::for_editor_in(follower_editor.clone(), &mut cx).await; + // follower_cx.assert_editor_state(indoc! {" + // ˇbase + + // "}); + // } } diff --git a/crates/multi_buffer/src/anchor.rs b/crates/multi_buffer/src/anchor.rs index 1c3be4b171890e871880d8a3fe9788872a98d789..4b23f344c9d27412daf6a630e04df9a2e67ff726 100644 --- a/crates/multi_buffer/src/anchor.rs +++ b/crates/multi_buffer/src/anchor.rs @@ -146,7 +146,7 @@ impl Anchor { .diffs .get(&excerpt.buffer_id) .map(|diff| diff.base_text()) - && a.buffer_id == Some(base_text.remote_id()) + && a.is_valid(&base_text) { return a.bias_left(base_text); } @@ -169,7 +169,7 @@ impl Anchor { .diffs .get(&excerpt.buffer_id) .map(|diff| diff.base_text()) - && a.buffer_id == Some(base_text.remote_id()) + && a.is_valid(&base_text) { return a.bias_right(base_text); } diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index 6e3dc71054de1b7ea193039988f412b16185f6e2..85fc14a934d173524542147386ba1856aa0149ce 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -624,8 +624,7 @@ pub struct MultiBufferSnapshot { replaced_excerpts: TreeMap, trailing_excerpt_update_count: usize, all_diff_hunks_expanded: bool, - // FIXME - pub show_deleted_hunks: bool, + show_deleted_hunks: bool, show_headers: bool, } @@ -2331,45 +2330,14 @@ impl MultiBuffer { let base_text_changed = snapshot .diffs .get(&buffer_id) - .is_none_or(|old_diff| !new_diff.base_texts_eq(old_diff)); + .is_none_or(|old_diff| !new_diff.base_texts_definitely_eq(old_diff)); snapshot.diffs.insert_or_replace(buffer_id, new_diff); self.buffer_changed_since_sync.replace(true); let buffer = buffer_state.buffer.read(cx); let diff_change_range = range.to_offset(buffer); - let mut excerpt_edits = Vec::new(); - for locator in &buffer_state.excerpts { - let mut cursor = snapshot - .excerpts - .cursor::, ExcerptOffset>>(()); - cursor.seek_forward(&Some(locator), Bias::Left); - if let Some(excerpt) = cursor.item() - && excerpt.locator == *locator - { - let excerpt_buffer_range = excerpt.range.context.to_offset(&excerpt.buffer); - if diff_change_range.end < excerpt_buffer_range.start - || diff_change_range.start > excerpt_buffer_range.end - { - continue; - } - let excerpt_start = cursor.start().1; - let excerpt_len = excerpt.text_summary.len; - let diff_change_start_in_excerpt = diff_change_range - .start - .saturating_sub(excerpt_buffer_range.start); - let diff_change_end_in_excerpt = diff_change_range - .end - .saturating_sub(excerpt_buffer_range.start); - let edit_start = excerpt_start + diff_change_start_in_excerpt.min(excerpt_len); - let edit_end = excerpt_start + diff_change_end_in_excerpt.min(excerpt_len); - excerpt_edits.push(Edit { - old: edit_start..edit_end, - new: edit_start..edit_end, - }); - } - } - + let excerpt_edits = snapshot.excerpt_edits_for_diff_change(buffer_state, diff_change_range); let edits = Self::sync_diff_transforms( &mut snapshot, excerpt_edits, @@ -2408,52 +2376,17 @@ impl MultiBuffer { .ok(), }; let mut snapshot = self.snapshot.get_mut(); - let base_text_changed = snapshot - .diffs - .get(&base_text_buffer_id) - .is_none_or(|old_diff| !new_diff.base_texts_eq(old_diff)); - snapshot .diffs .insert_or_replace(base_text_buffer_id, new_diff); - let mut excerpt_edits = Vec::new(); - for locator in &buffer_state.excerpts { - let mut cursor = snapshot - .excerpts - .cursor::, ExcerptOffset>>(()); - cursor.seek_forward(&Some(locator), Bias::Left); - if let Some(excerpt) = cursor.item() - && excerpt.locator == *locator - { - let excerpt_buffer_range = excerpt.range.context.to_offset(&excerpt.buffer); - if diff_change_range.end < excerpt_buffer_range.start - || diff_change_range.start > excerpt_buffer_range.end - { - continue; - } - let excerpt_start = cursor.start().1; - let excerpt_len = excerpt.text_summary.len; - let diff_change_start_in_excerpt = diff_change_range - .start - .saturating_sub(excerpt_buffer_range.start); - let diff_change_end_in_excerpt = diff_change_range - .end - .saturating_sub(excerpt_buffer_range.start); - let edit_start = excerpt_start + diff_change_start_in_excerpt.min(excerpt_len); - let edit_end = excerpt_start + diff_change_end_in_excerpt.min(excerpt_len); - excerpt_edits.push(Edit { - old: edit_start..edit_end, - new: edit_start..edit_end, - }); - } - } - + let excerpt_edits = snapshot.excerpt_edits_for_diff_change(buffer_state, diff_change_range); let edits = Self::sync_diff_transforms( &mut snapshot, excerpt_edits, DiffChangeKind::DiffUpdated { - base_changed: base_text_changed, + // We don't use read this field for inverted diffs. + base_changed: false, }, ); if !edits.is_empty() { @@ -6629,6 +6562,45 @@ impl MultiBufferSnapshot { debug_ranges.insert(key, text_ranges, format!("{value:?}").into()) }); } + + fn excerpt_edits_for_diff_change( + &self, + buffer_state: &BufferState, + diff_change_range: Range, + ) -> Vec>> { + let mut excerpt_edits = Vec::new(); + for locator in &buffer_state.excerpts { + let mut cursor = self + .excerpts + .cursor::, ExcerptOffset>>(()); + cursor.seek_forward(&Some(locator), Bias::Left); + if let Some(excerpt) = cursor.item() + && excerpt.locator == *locator + { + let excerpt_buffer_range = excerpt.range.context.to_offset(&excerpt.buffer); + if diff_change_range.end < excerpt_buffer_range.start + || diff_change_range.start > excerpt_buffer_range.end + { + continue; + } + let excerpt_start = cursor.start().1; + let excerpt_len = excerpt.text_summary.len; + let diff_change_start_in_excerpt = diff_change_range + .start + .saturating_sub(excerpt_buffer_range.start); + let diff_change_end_in_excerpt = diff_change_range + .end + .saturating_sub(excerpt_buffer_range.start); + let edit_start = excerpt_start + diff_change_start_in_excerpt.min(excerpt_len); + let edit_end = excerpt_start + diff_change_end_in_excerpt.min(excerpt_len); + excerpt_edits.push(Edit { + old: edit_start..edit_end, + new: edit_start..edit_end, + }); + } + } + excerpt_edits + } } #[cfg(any(test, feature = "test-support"))] diff --git a/crates/multi_buffer/src/multi_buffer_tests.rs b/crates/multi_buffer/src/multi_buffer_tests.rs index 7c896fb9e582fa78d331f860cf22f4165a7ea522..6c605170c056163caebce8565caca061b3f4ccbe 100644 --- a/crates/multi_buffer/src/multi_buffer_tests.rs +++ b/crates/multi_buffer/src/multi_buffer_tests.rs @@ -12,13 +12,6 @@ use util::RandomCharIter; use util::rel_path::rel_path; use util::test::sample_text; -// FIXME -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum MultiBufferFilterMode { - KeepInsertions, - KeepDeletions, -} - #[ctor::ctor] fn init_logger() { zlog::init_test(); @@ -2376,13 +2369,11 @@ impl ReferenceMultibuffer { fn expected_content( &self, - filter_mode: Option, all_diff_hunks_expanded: bool, cx: &App, ) -> (String, Vec, HashSet) { let mut text = String::new(); let mut regions = Vec::::new(); - let mut filtered_regions = Vec::::new(); let mut excerpt_boundary_rows = HashSet::default(); for excerpt in &self.excerpts { excerpt_boundary_rows.insert(MultiBufferRow(text.matches('\n').count() as u32)); @@ -2441,9 +2432,7 @@ impl ReferenceMultibuffer { } // Add the deleted text for the hunk. - if !hunk.diff_base_byte_range.is_empty() - && filter_mode != Some(MultiBufferFilterMode::KeepInsertions) - { + if !hunk.diff_base_byte_range.is_empty() { let mut base_text = base_buffer .text_for_range(hunk.diff_base_byte_range.clone()) .collect::(); @@ -2466,14 +2455,9 @@ impl ReferenceMultibuffer { // Add the inserted text for the hunk. if hunk_range.end > offset { - let is_filtered = filter_mode == Some(MultiBufferFilterMode::KeepDeletions); - let range = if is_filtered { - text.len()..text.len() - } else { - let len = text.len(); - text.extend(buffer.text_for_range(offset..hunk_range.end)); - len..text.len() - }; + let len = text.len(); + text.extend(buffer.text_for_range(offset..hunk_range.end)); + let range = len..text.len(); let region = ReferenceRegion { buffer_id: Some(buffer.remote_id()), range, @@ -2482,11 +2466,7 @@ impl ReferenceMultibuffer { excerpt_id: Some(excerpt.id), }; offset = hunk_range.end; - if is_filtered { - filtered_regions.push(region); - } else { - regions.push(region); - } + regions.push(region); } } @@ -2711,23 +2691,6 @@ async fn test_random_set_ranges(cx: &mut TestAppContext, mut rng: StdRng) { } } -// FIXME -// #[gpui::test(iterations = 100)] -// async fn test_random_filtered_multibuffer(cx: &mut TestAppContext, rng: StdRng) { -// let multibuffer = cx.new(|cx| { -// let mut multibuffer = MultiBuffer::new(Capability::ReadWrite); -// multibuffer.set_all_diff_hunks_expanded(cx); -// multibuffer.set_filter_mode(Some(MultiBufferFilterMode::KeepInsertions)); -// multibuffer -// }); -// let follower = multibuffer.update(cx, |multibuffer, cx| multibuffer.get_or_create_follower(cx)); -// follower.update(cx, |follower, _| { -// assert!(follower.all_diff_hunks_expanded()); -// follower.set_filter_mode(Some(MultiBufferFilterMode::KeepDeletions)); -// }); -// test_random_multibuffer_impl(multibuffer, cx, rng).await; -// } - #[gpui::test(iterations = 100)] async fn test_random_multibuffer(cx: &mut TestAppContext, rng: StdRng) { let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite)); @@ -2994,9 +2957,6 @@ fn check_multibuffer( rng: &mut StdRng, ) { let snapshot = multibuffer.snapshot(cx); - // FIXME - let filter_mode = None; - assert!(filter_mode.is_some() == snapshot.all_diff_hunks_expanded); let actual_text = snapshot.text(); let actual_boundary_rows = snapshot .excerpt_boundaries_in_range(MultiBufferOffset(0)..) @@ -3005,15 +2965,12 @@ fn check_multibuffer( let actual_row_infos = snapshot.row_infos(MultiBufferRow(0)).collect::>(); let (expected_text, expected_row_infos, expected_boundary_rows) = - reference.expected_content(filter_mode, snapshot.all_diff_hunks_expanded, cx); - - let (unfiltered_text, unfiltered_row_infos, unfiltered_boundary_rows) = - reference.expected_content(None, snapshot.all_diff_hunks_expanded, cx); + reference.expected_content(snapshot.all_diff_hunks_expanded, cx); let has_diff = actual_row_infos .iter() .any(|info| info.diff_status.is_some()) - || unfiltered_row_infos + || expected_row_infos .iter() .any(|info| info.diff_status.is_some()); let actual_diff = format_diff( @@ -3030,17 +2987,6 @@ fn check_multibuffer( ); log::info!("Multibuffer content:\n{}", actual_diff); - if filter_mode.is_some() { - log::info!( - "Unfiltered multibuffer content:\n{}", - format_diff( - &unfiltered_text, - &unfiltered_row_infos, - &unfiltered_boundary_rows, - None, - ), - ); - } assert_eq!( actual_row_infos.len(), @@ -3714,6 +3660,11 @@ fn format_diff( // .join("\n") // } +// FIXME test: +// - multibuffer with multiple excerpts having inverted diffs +// - via randomized test? +// - diff hunk navigation when diff is inverted +// - inverted diff language changing #[gpui::test] async fn test_inverted_diff(cx: &mut TestAppContext) { let text = indoc!( @@ -3741,7 +3692,7 @@ async fn test_inverted_diff(cx: &mut TestAppContext) { .new(|cx| BufferDiff::new_with_base_text(base_text, &buffer.read(cx).text_snapshot(), cx)); cx.run_until_parked(); - let base_text_buffer = cx.new(|cx| Buffer::local(base_text, cx)); + let base_text_buffer = diff.read_with(cx, |diff, cx| diff.base_text_buffer()); let multibuffer = cx.new(|cx| { let mut multibuffer = MultiBuffer::singleton(base_text_buffer.clone(), cx); @@ -3805,7 +3756,7 @@ async fn test_inverted_diff(cx: &mut TestAppContext) { }) .await; diff.update(cx, |diff, cx| { - diff.set_snapshot(update, &buffer.read(cx).text_snapshot(), false, cx) + diff.set_snapshot(update, &buffer.read(cx).text_snapshot(), false, cx); }); cx.run_until_parked(); @@ -3825,6 +3776,28 @@ async fn test_inverted_diff(cx: &mut TestAppContext) { " }, ); + + diff.update(cx, |diff, cx| { + diff.set_base_text( + Some("new base\n".into()), + None, + buffer.read(cx).text_snapshot(), + cx, + ) + }) + .await + .unwrap(); + cx.run_until_parked(); + + assert_new_snapshot( + &multibuffer, + &mut snapshot, + &mut subscription, + cx, + indoc! {" + - new base + "}, + ); } #[track_caller]