Skip to content

Commit

Permalink
fix: panic when goto_impl has empty locations
Browse files Browse the repository at this point in the history
  • Loading branch information
Desdaemon committed Apr 1, 2024
1 parent cd85d4c commit dd9edba
Showing 1 changed file with 32 additions and 21 deletions.
53 changes: 32 additions & 21 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use futures_util::{future::join_all, stream::FuturesUnordered, FutureExt};
use futures_util::{stream::FuturesUnordered, FutureExt};
use helix_lsp::{
block_on,
lsp::{
Expand Down Expand Up @@ -924,13 +924,15 @@ where
goto_impl(editor, compositor, vec![single], MAPPINGS[encodings[idx]]);
return;
}
lsp::GotoDefinitionResponse::Array(many) => {
lsp::GotoDefinitionResponse::Array(many) if !many.is_empty() => {
goto_impl(editor, compositor, many, MAPPINGS[encodings[idx]]);
return;
}
_ => {}
}
}
editor.set_status("No definitions found.");
return;
},
);
}
Expand Down Expand Up @@ -1009,30 +1011,39 @@ pub fn hover(cx: &mut Context) {
let (view, doc) = current!(cx.editor);

let language_servers = doc.language_servers_with_feature(LanguageServerFeature::Hover);
let mut future = vec![];
for server in language_servers {
// TODO: factor out a doc.position_identifier() that returns lsp::TextDocumentPositionIdentifier
let pos = doc.position(view.id, server.offset_encoding());
if let Some(resp) = server.text_document_hover(doc.identifier(), pos, None) {
future.push(resp);
}
}

if future.is_empty() {
let mut futures: FuturesUnordered<_> = language_servers
.map(|server| {
// TODO: factor out a doc.position_identifier() that returns lsp::TextDocumentPositionIdentifier
let pos = doc.position(view.id, server.offset_encoding());
server
.text_document_hover(doc.identifier(), pos, None)
.unwrap()
})
.collect();
if futures.is_empty() {
cx.editor
.set_status("No configured language server supports hover");
return;
}

let future = join_all(future).map(|data| {
Ok(data
.into_iter()
.flat_map(|resp| {
let resp = resp.ok()?;
(!resp.is_null()).then_some(resp)
})
.collect())
});
let future = async move {
let mut responses = Vec::with_capacity(futures.len());

loop {
let res = match futures.try_next().await {
Ok(Some(res)) => res,
Ok(None) => break,
Err(err) => {
log::error!(target: "hover", "{err}");
continue;
}
};
if !res.is_null() {
responses.push(res);
}
}
Ok(serde_json::Value::Array(responses))
};

cx.callback(future, move |editor, compositor, hover: Vec<lsp::Hover>| {
// hover.contents / .range <- used for visualizing
Expand Down

0 comments on commit dd9edba

Please sign in to comment.