lsp: Add support for default rename behavior in prepareRename request (#24246)

Piotr Osiewicz created

Fixes #24184

Release Notes:

- Fixed renaming not working with some language servers (e.g. hls)

Change summary

crates/lsp/src/lsp.rs             |  3 ++
crates/project/src/lsp_command.rs | 37 ++++++++++++++++----------------
2 files changed, 21 insertions(+), 19 deletions(-)

Detailed changes

crates/lsp/src/lsp.rs 🔗

@@ -724,6 +724,9 @@ impl LanguageServer {
                     }),
                     rename: Some(RenameClientCapabilities {
                         prepare_support: Some(true),
+                        prepare_support_default_behavior: Some(
+                            PrepareSupportDefaultBehavior::IDENTIFIER,
+                        ),
                         ..Default::default()
                     }),
                     hover: Some(HoverClientCapabilities {

crates/project/src/lsp_command.rs 🔗

@@ -299,28 +299,27 @@ impl LspCommand for PrepareRename {
         _: LanguageServerId,
         mut cx: AsyncApp,
     ) -> Result<PrepareRenameResponse> {
-        buffer.update(&mut cx, |buffer, _| {
-            match message {
-                Some(lsp::PrepareRenameResponse::Range(range))
-                | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
-                    let Range { start, end } = range_from_lsp(range);
-                    if buffer.clip_point_utf16(start, Bias::Left) == start.0
-                        && buffer.clip_point_utf16(end, Bias::Left) == end.0
-                    {
-                        Ok(PrepareRenameResponse::Success(
-                            buffer.anchor_after(start)..buffer.anchor_before(end),
-                        ))
-                    } else {
-                        Ok(PrepareRenameResponse::InvalidPosition)
-                    }
-                }
-                Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
-                    Err(anyhow!("Invalid for language server to send a `defaultBehavior` response to `prepareRename`"))
-                }
-                None => {
+        buffer.update(&mut cx, |buffer, _| match message {
+            Some(lsp::PrepareRenameResponse::Range(range))
+            | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
+                let Range { start, end } = range_from_lsp(range);
+                if buffer.clip_point_utf16(start, Bias::Left) == start.0
+                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
+                {
+                    Ok(PrepareRenameResponse::Success(
+                        buffer.anchor_after(start)..buffer.anchor_before(end),
+                    ))
+                } else {
                     Ok(PrepareRenameResponse::InvalidPosition)
                 }
             }
+            Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
+                let snapshot = buffer.snapshot();
+                let (range, _) = snapshot.surrounding_word(self.position);
+                let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
+                Ok(PrepareRenameResponse::Success(range))
+            }
+            None => Ok(PrepareRenameResponse::InvalidPosition),
         })?
     }