diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 7f504ecedc..47b16e2633 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -3829,7 +3829,16 @@ mod tests { }, Some(tree_sitter_rust::language()), ); - let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + let mut fake_language_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: Default::default(), + })), + ..Default::default() + }, + ..Default::default() + }); lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1df5856843..9be20ba2eb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4632,7 +4632,23 @@ impl Editor { }); Some(cx.spawn(|this, mut cx| async move { - if let Some(rename_range) = prepare_rename.await? { + let rename_range = if let Some(range) = prepare_rename.await? { + Some(range) + } else { + this.read_with(&cx, |this, cx| { + let buffer = this.buffer.read(cx).snapshot(cx); + let mut buffer_highlights = this + .document_highlights_for_position(selection.head(), &buffer) + .filter(|highlight| { + highlight.start.excerpt_id() == selection.head().excerpt_id() + && highlight.end.excerpt_id() == selection.head().excerpt_id() + }); + buffer_highlights + .next() + .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor) + }) + }; + if let Some(rename_range) = rename_range { let rename_buffer_range = rename_range.to_offset(&snapshot); let cursor_offset_in_rename_range = cursor_buffer_offset.saturating_sub(rename_buffer_range.start); @@ -5677,6 +5693,43 @@ impl Editor { self.background_highlights_in_range(start..end, &snapshot, theme) } + fn document_highlights_for_position<'a>( + &'a self, + position: Anchor, + buffer: &'a MultiBufferSnapshot, + ) -> impl 'a + Iterator> { + let read_highlights = self + .background_highlights + .get(&TypeId::of::()) + .map(|h| &h.1); + let write_highlights = self + .background_highlights + .get(&TypeId::of::()) + .map(|h| &h.1); + let left_position = position.bias_left(buffer); + let right_position = position.bias_right(buffer); + read_highlights + .into_iter() + .chain(write_highlights) + .flat_map(move |ranges| { + let start_ix = match ranges.binary_search_by(|probe| { + let cmp = probe.end.cmp(&left_position, &buffer); + if cmp.is_ge() { + Ordering::Greater + } else { + Ordering::Less + } + }) { + Ok(i) | Err(i) => i, + }; + + let right_position = right_position.clone(); + ranges[start_ix..] + .iter() + .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le()) + }) + } + pub fn background_highlights_in_range( &self, search_range: Range, diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index c0b21eeeda..02bc0486f1 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -292,6 +292,10 @@ impl LanguageServer { }), ..Default::default() }), + rename: Some(RenameClientCapabilities { + prepare_support: Some(true), + ..Default::default() + }), ..Default::default() }), experimental: Some(json!({ diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 71ad489d07..1e86bb2719 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -86,6 +86,14 @@ impl LspCommand for PrepareRename { type LspRequest = lsp::request::PrepareRenameRequest; type ProtoRequest = proto::PrepareRename; + fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool { + if let Some(lsp::OneOf::Right(rename)) = &capabilities.rename_provider { + rename.prepare_provider == Some(true) + } else { + false + } + } + fn to_lsp(&self, path: &Path, _: &AppContext) -> lsp::TextDocumentPositionParams { lsp::TextDocumentPositionParams { text_document: lsp::TextDocumentIdentifier { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index fbbba31d8f..c2e444741e 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -7466,7 +7466,16 @@ mod tests { }, Some(tree_sitter_rust::language()), ); - let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); + let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: Default::default(), + })), + ..Default::default() + }, + ..Default::default() + }); let fs = FakeFs::new(cx.background()); fs.insert_tree(