lsp: Add partial support for insert/replace completions (#9634)

Piotr Osiewicz created

Most notably, this should do away with completions overriding the whole
word around completion trigger text. Fixes: #4816



Release Notes:

- Fixed code completions overriding text around the cursor.

Change summary

crates/lsp/src/lsp.rs             |  1 +
crates/project/src/lsp_command.rs | 16 +++++++++++++---
2 files changed, 14 insertions(+), 3 deletions(-)

Detailed changes

crates/lsp/src/lsp.rs 🔗

@@ -590,6 +590,7 @@ impl LanguageServer {
                                     "additionalTextEdits".to_string(),
                                 ],
                             }),
+                            insert_replace_support: Some(true),
                             ..Default::default()
                         }),
                         completion_list: Some(CompletionListCapability {

crates/project/src/lsp_command.rs 🔗

@@ -1557,9 +1557,19 @@ impl LspCommand for GetCompletions {
                             (range, text)
                         }
 
-                        Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => {
-                            log::info!("unsupported insert/replace completion");
-                            return None;
+                        Some(lsp::CompletionTextEdit::InsertAndReplace(edit)) => {
+                            let range = range_from_lsp(edit.insert);
+
+                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
+                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
+                            if start != range.start.0 || end != range.end.0 {
+                                log::info!("completion out of expected range");
+                                return None;
+                            }
+                            (
+                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
+                                edit.new_text.clone(),
+                            )
                         }
                     };