Open folds containing selections when jumping from multibuffer (#21433)

Cole Miller created

When searching within a single buffer, activating a search result causes
any fold containing the result to be unfolded. However, this didn't
happen when jumping to a search result from a project-wide search
multibuffer. This PR fixes that.

Release Notes:

- Fixed folds not opening when jumping from search results multibuffer

Change summary

crates/editor/src/editor.rs       |  1 
crates/editor/src/editor_tests.rs | 70 ++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 1 deletion(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -12876,6 +12876,7 @@ impl Editor {
                             None => Autoscroll::newest(),
                         };
                         let nav_history = editor.nav_history.take();
+                        editor.unfold_ranges(&ranges, false, true, cx);
                         editor.change_selections(Some(autoscroll), cx, |s| {
                             s.select_ranges(ranges);
                         });

crates/editor/src/editor_tests.rs 🔗

@@ -11567,7 +11567,7 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
 }
 
 #[gpui::test]
-async fn test_mutlibuffer_in_navigation_history(cx: &mut gpui::TestAppContext) {
+async fn test_multibuffer_in_navigation_history(cx: &mut gpui::TestAppContext) {
     init_test(cx, |_| {});
 
     let cols = 4;
@@ -11856,6 +11856,74 @@ async fn test_mutlibuffer_in_navigation_history(cx: &mut gpui::TestAppContext) {
         .unwrap();
 }
 
+#[gpui::test]
+async fn test_multibuffer_unfold_on_jump(cx: &mut gpui::TestAppContext) {
+    init_test(cx, |_| {});
+
+    let texts = ["{\n\tx\n}".to_owned(), "y".to_owned()];
+    let buffers = texts
+        .clone()
+        .map(|txt| cx.new_model(|cx| Buffer::local(txt, cx)));
+    let multi_buffer = cx.new_model(|cx| {
+        let mut multi_buffer = MultiBuffer::new(ReadWrite);
+        for i in 0..2 {
+            multi_buffer.push_excerpts(
+                buffers[i].clone(),
+                [ExcerptRange {
+                    context: 0..texts[i].len(),
+                    primary: None,
+                }],
+                cx,
+            );
+        }
+        multi_buffer
+    });
+
+    let fs = FakeFs::new(cx.executor());
+    fs.insert_tree(
+        "/project",
+        json!({
+            "x": &texts[0],
+            "y": &texts[1],
+        }),
+    )
+    .await;
+    let project = Project::test(fs, ["/project".as_ref()], cx).await;
+    let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+    let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
+
+    let multi_buffer_editor = cx.new_view(|cx| {
+        Editor::for_multibuffer(multi_buffer.clone(), Some(project.clone()), true, cx)
+    });
+    let buffer_editor =
+        cx.new_view(|cx| Editor::for_buffer(buffers[0].clone(), Some(project.clone()), cx));
+    workspace
+        .update(cx, |workspace, cx| {
+            workspace.add_item_to_active_pane(
+                Box::new(multi_buffer_editor.clone()),
+                None,
+                true,
+                cx,
+            );
+            workspace.add_item_to_active_pane(Box::new(buffer_editor.clone()), None, false, cx);
+        })
+        .unwrap();
+    cx.executor().run_until_parked();
+    buffer_editor.update(cx, |buffer_editor, cx| {
+        buffer_editor.fold_at_level(&FoldAtLevel { level: 1 }, cx);
+        assert!(buffer_editor.snapshot(cx).fold_count() == 1);
+    });
+    cx.executor().run_until_parked();
+    multi_buffer_editor.update(cx, |multi_buffer_editor, cx| {
+        multi_buffer_editor.change_selections(None, cx, |s| s.select_ranges([3..4]));
+        multi_buffer_editor.open_excerpts(&OpenExcerpts, cx);
+    });
+    cx.executor().run_until_parked();
+    buffer_editor.update(cx, |buffer_editor, cx| {
+        assert!(buffer_editor.snapshot(cx).fold_count() == 0);
+    });
+}
+
 #[gpui::test]
 async fn test_toggle_hunk_diff(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
     init_test(cx, |_| {});