Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/handlers/signature_help.rs')
-rw-r--r--helix-term/src/handlers/signature_help.rs112
1 files changed, 67 insertions, 45 deletions
diff --git a/helix-term/src/handlers/signature_help.rs b/helix-term/src/handlers/signature_help.rs
index 3c746548..0bb1d3d1 100644
--- a/helix-term/src/handlers/signature_help.rs
+++ b/helix-term/src/handlers/signature_help.rs
@@ -5,7 +5,7 @@ use helix_core::syntax::LanguageServerFeature;
use helix_event::{
cancelable_future, cancelation, register_hook, send_blocking, CancelRx, CancelTx,
};
-use helix_lsp::lsp;
+use helix_lsp::lsp::{self, SignatureInformation};
use helix_stdx::rope::RopeSliceExt;
use helix_view::document::Mode;
use helix_view::events::{DocumentDidChange, SelectionDidChange};
@@ -18,7 +18,7 @@ use crate::commands::Open;
use crate::compositor::Compositor;
use crate::events::{OnModeSwitch, PostInsertChar};
use crate::handlers::Handlers;
-use crate::ui::lsp::SignatureHelp;
+use crate::ui::lsp::{Signature, SignatureHelp};
use crate::ui::Popup;
use crate::{job, ui};
@@ -82,6 +82,7 @@ impl helix_event::AsyncHook for SignatureHelpHandler {
}
}
self.state = if open { State::Open } else { State::Closed };
+
return timeout;
}
}
@@ -138,6 +139,31 @@ pub fn request_signature_help(
});
}
+fn active_param_range(
+ signature: &SignatureInformation,
+ response_active_parameter: Option<u32>,
+) -> Option<(usize, usize)> {
+ let param_idx = signature
+ .active_parameter
+ .or(response_active_parameter)
+ .unwrap_or(0) as usize;
+ let param = signature.parameters.as_ref()?.get(param_idx)?;
+ match &param.label {
+ lsp::ParameterLabel::Simple(string) => {
+ let start = signature.label.find(string.as_str())?;
+ Some((start, start + string.len()))
+ }
+ lsp::ParameterLabel::LabelOffsets([start, end]) => {
+ // LS sends offsets based on utf-16 based string representation
+ // but highlighting in helix is done using byte offset.
+ use helix_core::str_utils::char_to_byte_idx;
+ let from = char_to_byte_idx(&signature.label, *start as usize);
+ let to = char_to_byte_idx(&signature.label, *end as usize);
+ Some((from, to))
+ }
+ }
+}
+
pub fn show_signature_help(
editor: &mut Editor,
compositor: &mut Compositor,
@@ -184,54 +210,50 @@ pub fn show_signature_help(
let doc = doc!(editor);
let language = doc.language_name().unwrap_or("");
- let signature = match response
+ if response.signatures.is_empty() {
+ return;
+ }
+
+ let signatures: Vec<Signature> = response
.signatures
- .get(response.active_signature.unwrap_or(0) as usize)
- {
- Some(s) => s,
- None => return,
- };
- let mut contents = SignatureHelp::new(
- signature.label.clone(),
+ .into_iter()
+ .map(|s| {
+ let active_param_range = active_param_range(&s, response.active_parameter);
+
+ let signature_doc = if config.lsp.display_signature_help_docs {
+ s.documentation.map(|doc| match doc {
+ lsp::Documentation::String(s) => s,
+ lsp::Documentation::MarkupContent(markup) => markup.value,
+ })
+ } else {
+ None
+ };
+
+ Signature {
+ signature: s.label,
+ signature_doc,
+ active_param_range,
+ }
+ })
+ .collect();
+
+ let old_popup = compositor.find_id::<Popup<SignatureHelp>>(SignatureHelp::ID);
+ let mut active_signature = old_popup
+ .as_ref()
+ .map(|popup| popup.contents().active_signature())
+ .unwrap_or_else(|| response.active_signature.unwrap_or_default() as usize);
+
+ if active_signature >= signatures.len() {
+ active_signature = signatures.len() - 1;
+ }
+
+ let contents = SignatureHelp::new(
language.to_string(),
Arc::clone(&editor.syn_loader),
+ active_signature,
+ signatures,
);
- let signature_doc = if config.lsp.display_signature_help_docs {
- signature.documentation.as_ref().map(|doc| match doc {
- lsp::Documentation::String(s) => s.clone(),
- lsp::Documentation::MarkupContent(markup) => markup.value.clone(),
- })
- } else {
- None
- };
-
- contents.set_signature_doc(signature_doc);
-
- let active_param_range = || -> Option<(usize, usize)> {
- let param_idx = signature
- .active_parameter
- .or(response.active_parameter)
- .unwrap_or(0) as usize;
- let param = signature.parameters.as_ref()?.get(param_idx)?;
- match &param.label {
- lsp::ParameterLabel::Simple(string) => {
- let start = signature.label.find(string.as_str())?;
- Some((start, start + string.len()))
- }
- lsp::ParameterLabel::LabelOffsets([start, end]) => {
- // LS sends offsets based on utf-16 based string representation
- // but highlighting in helix is done using byte offset.
- use helix_core::str_utils::char_to_byte_idx;
- let from = char_to_byte_idx(&signature.label, *start as usize);
- let to = char_to_byte_idx(&signature.label, *end as usize);
- Some((from, to))
- }
- }
- };
- contents.set_active_param_range(active_param_range());
-
- let old_popup = compositor.find_id::<Popup<SignatureHelp>>(SignatureHelp::ID);
let mut popup = Popup::new(SignatureHelp::ID, contents)
.position(old_popup.and_then(|p| p.get_position()))
.position_bias(Open::Above)