Select applicable positions for lsp_ext methods more leniently (#32272)

Kirill Bulatov created

Closes https://github.com/zed-industries/zed/issues/27238

Release Notes:

- Fixed `editor::SwitchSourceHeader` and
`editor::ExpandMacroRecursively` not working with text selections

Change summary

crates/collab/src/tests/editor_tests.rs | 11 ++++++++---
crates/editor/src/lsp_ext.rs            |  5 ++---
crates/editor/src/rust_analyzer_ext.rs  |  3 ---
crates/text/src/selection.rs            |  2 ++
4 files changed, 12 insertions(+), 9 deletions(-)

Detailed changes

crates/collab/src/tests/editor_tests.rs 🔗

@@ -7,7 +7,7 @@ use editor::{
     Editor, RowInfo,
     actions::{
         ConfirmCodeAction, ConfirmCompletion, ConfirmRename, ContextMenuFirst,
-        ExpandMacroRecursively, Redo, Rename, ToggleCodeActions, Undo,
+        ExpandMacroRecursively, Redo, Rename, SelectAll, ToggleCodeActions, Undo,
     },
     test::{
         editor_test_context::{AssertionContextManager, EditorTestContext},
@@ -2712,7 +2712,7 @@ async fn test_client_can_query_lsp_ext(cx_a: &mut TestAppContext, cx_b: &mut Tes
                 params.text_document.uri,
                 lsp::Url::from_file_path(path!("/a/main.rs")).unwrap(),
             );
-            assert_eq!(params.position, lsp::Position::new(0, 0),);
+            assert_eq!(params.position, lsp::Position::new(0, 0));
             Ok(Some(ExpandedMacro {
                 name: "test_macro_name".to_string(),
                 expansion: "test_macro_expansion on the host".to_string(),
@@ -2747,7 +2747,11 @@ async fn test_client_can_query_lsp_ext(cx_a: &mut TestAppContext, cx_b: &mut Tes
                 params.text_document.uri,
                 lsp::Url::from_file_path(path!("/a/main.rs")).unwrap(),
             );
-            assert_eq!(params.position, lsp::Position::new(0, 0),);
+            assert_eq!(
+                params.position,
+                lsp::Position::new(0, 12),
+                "editor_b has selected the entire text and should query for a different position"
+            );
             Ok(Some(ExpandedMacro {
                 name: "test_macro_name".to_string(),
                 expansion: "test_macro_expansion on the client".to_string(),
@@ -2756,6 +2760,7 @@ async fn test_client_can_query_lsp_ext(cx_a: &mut TestAppContext, cx_b: &mut Tes
     );
 
     editor_b.update_in(cx_b, |editor, window, cx| {
+        editor.select_all(&SelectAll, window, cx);
         expand_macro_recursively(editor, &ExpandMacroRecursively, window, cx)
     });
     expand_request_b.next().await.unwrap();

crates/editor/src/lsp_ext.rs 🔗

@@ -42,8 +42,8 @@ where
         .selections
         .disjoint_anchors()
         .iter()
-        .filter(|selection| selection.start == selection.end)
-        .filter_map(|selection| Some((selection.start, selection.start.buffer_id?)))
+        .filter_map(|selection| Some((selection.head(), selection.head().buffer_id?)))
+        .unique_by(|(_, buffer_id)| *buffer_id)
         .filter_map(|(trigger_anchor, buffer_id)| {
             let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
             let language = buffer.read(cx).language_at(trigger_anchor.text_anchor)?;
@@ -53,7 +53,6 @@ where
                 None
             }
         })
-        .unique_by(|(_, buffer, _)| buffer.read(cx).remote_id())
         .collect::<Vec<_>>();
 
     let applicable_buffer_tasks = applicable_buffers

crates/editor/src/rust_analyzer_ext.rs 🔗

@@ -132,9 +132,6 @@ pub fn expand_macro_recursively(
     window: &mut Window,
     cx: &mut Context<Editor>,
 ) {
-    if editor.selections.count() == 0 {
-        return;
-    }
     let Some(project) = &editor.project else {
         return;
     };

crates/text/src/selection.rs 🔗

@@ -26,6 +26,7 @@ impl Default for SelectionGoal {
 }
 
 impl<T: Clone> Selection<T> {
+    /// A place where the selection had stopped at.
     pub fn head(&self) -> T {
         if self.reversed {
             self.start.clone()
@@ -34,6 +35,7 @@ impl<T: Clone> Selection<T> {
         }
     }
 
+    /// A place where selection was initiated from.
     pub fn tail(&self) -> T {
         if self.reversed {
             self.end.clone()