LSP: Support multiple langauge servers for goto references

This refactors goto_reference like the parent commit to query all
language servers supporting the feature.
This commit is contained in:
Michael Davis 2025-01-30 10:04:01 -05:00
parent f7394d53fd
commit 1a821ac726
No known key found for this signature in database

View file

@ -985,38 +985,47 @@ pub fn goto_implementation(cx: &mut Context) {
pub fn goto_reference(cx: &mut Context) { pub fn goto_reference(cx: &mut Context) {
let config = cx.editor.config(); let config = cx.editor.config();
let (view, doc) = current!(cx.editor); let (view, doc) = current_ref!(cx.editor);
// TODO could probably support multiple language servers, let mut futures: FuturesOrdered<_> = doc
// not sure if there's a real practical use case for this though .language_servers_with_feature(LanguageServerFeature::GotoReference)
let language_server = .map(|language_server| {
language_server_with_feature!(cx.editor, doc, LanguageServerFeature::GotoReference); let offset_encoding = language_server.offset_encoding();
let offset_encoding = language_server.offset_encoding(); let pos = doc.position(view.id, offset_encoding);
let pos = doc.position(view.id, offset_encoding); let future = language_server
let future = language_server .goto_reference(
.goto_reference( doc.identifier(),
doc.identifier(), pos,
pos, config.lsp.goto_reference_include_declaration,
config.lsp.goto_reference_include_declaration, None,
None, )
) .unwrap();
.unwrap(); async move {
let json = future.await?;
let locations: Vec<lsp::Location> = serde_json::from_value(json)?;
anyhow::Ok((locations, offset_encoding))
}
})
.collect();
cx.callback( cx.jobs.callback(async move {
future, let mut locations = Vec::new();
move |editor, compositor, response: Option<Vec<lsp::Location>>| { while let Some((lsp_locations, offset_encoding)) = futures.try_next().await? {
let items: Vec<Location> = response locations.extend(
.into_iter() lsp_locations
.flatten() .into_iter()
.flat_map(|location| lsp_location_to_location(location, offset_encoding)) .flat_map(|location| lsp_location_to_location(location, offset_encoding)),
.collect(); );
if items.is_empty() { }
let call = move |editor: &mut Editor, compositor: &mut Compositor| {
if locations.is_empty() {
editor.set_error("No references found."); editor.set_error("No references found.");
} else { } else {
goto_impl(editor, compositor, items); goto_impl(editor, compositor, locations);
} }
}, };
); Ok(Callback::EditorCompositor(Box::new(call)))
});
} }
pub fn signature_help(cx: &mut Context) { pub fn signature_help(cx: &mut Context) {