editor: Fix buffer fold focuses first buffer in multi-buffer instead of the toggled one (#44394)

Smit Barmase created

Closes #43870

Regressed in https://github.com/zed-industries/zed/pull/37953

Release Notes:

- Fixed issue where toggling buffer fold focuses first buffer in
multi-buffer instead of the toggled one.

Change summary

crates/editor/src/editor_tests.rs          | 13 ++++++-------
crates/editor/src/selections_collection.rs | 13 ++++++++++---
crates/outline_panel/src/outline_panel.rs  | 10 ++++++----
3 files changed, 22 insertions(+), 14 deletions(-)

Detailed changes

crates/editor/src/editor_tests.rs 🔗

@@ -28599,33 +28599,32 @@ async fn test_multibuffer_selections_with_folding(cx: &mut TestAppContext) {
         3
         "});
 
-    // Edge case scenario: fold all buffers, then try to insert
+    // Test correct folded header is selected upon fold
     cx.update_editor(|editor, _, cx| {
         editor.fold_buffer(buffer_ids[0], cx);
         editor.fold_buffer(buffer_ids[1], cx);
     });
     cx.assert_excerpts_with_selections(indoc! {"
-        [EXCERPT]
-        ˇ[FOLDED]
         [EXCERPT]
         [FOLDED]
+        [EXCERPT]
+        ˇ[FOLDED]
         "});
 
-    // Insert should work via default selection
+    // Test selection inside folded buffer unfolds it on type
     cx.update_editor(|editor, window, cx| {
         editor.handle_input("W", window, cx);
     });
     cx.update_editor(|editor, _, cx| {
         editor.unfold_buffer(buffer_ids[0], cx);
-        editor.unfold_buffer(buffer_ids[1], cx);
     });
     cx.assert_excerpts_with_selections(indoc! {"
         [EXCERPT]
-        Wˇ1
+        1
         2
         3
         [EXCERPT]
-        1
+        Wˇ1
         Z
         3
         "});

crates/editor/src/selections_collection.rs 🔗

@@ -540,11 +540,18 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
         };
 
         if filtered_selections.is_empty() {
-            let default_anchor = self.snapshot.anchor_before(MultiBufferOffset(0));
+            let buffer_snapshot = self.snapshot.buffer_snapshot();
+            let anchor = buffer_snapshot
+                .excerpts()
+                .find(|(_, buffer, _)| buffer.remote_id() == buffer_id)
+                .and_then(|(excerpt_id, _, range)| {
+                    buffer_snapshot.anchor_in_excerpt(excerpt_id, range.context.start)
+                })
+                .unwrap_or_else(|| self.snapshot.anchor_before(MultiBufferOffset(0)));
             self.collection.disjoint = Arc::from([Selection {
                 id: post_inc(&mut self.collection.next_selection_id),
-                start: default_anchor,
-                end: default_anchor,
+                start: anchor,
+                end: anchor,
                 reversed: false,
                 goal: SelectionGoal::None,
             }]);

crates/outline_panel/src/outline_panel.rs 🔗

@@ -6579,11 +6579,13 @@ outline: struct OutlineEntryExcerpt
                 format!(
                     r#"frontend-project/
   public/lottie/
-    syntax-tree.json  <==== selected
+    syntax-tree.json
+      search: {{ "something": "«static»" }}
   src/
     app/(site)/
     components/
-      ErrorBoundary.tsx"#
+      ErrorBoundary.tsx  <==== selected
+        search: «static»"#
                 )
             );
         });
@@ -6625,7 +6627,7 @@ outline: struct OutlineEntryExcerpt
                 format!(
                     r#"frontend-project/
   public/lottie/
-    syntax-tree.json  <==== selected
+    syntax-tree.json
       search: {{ "something": "«static»" }}
   src/
     app/(site)/
@@ -6636,7 +6638,7 @@ outline: struct OutlineEntryExcerpt
         page.tsx
           search: «static»
     components/
-      ErrorBoundary.tsx
+      ErrorBoundary.tsx  <==== selected
         search: «static»"#
                 )
             );