Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/commands/lsp.rs')
| -rw-r--r-- | helix-term/src/commands/lsp.rs | 174 |
1 files changed, 2 insertions, 172 deletions
diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 8377f7c7..f4abf6e8 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -13,18 +13,9 @@ use tui::{text::Span, widgets::Row}; use super::{align_view, push_jump, Align, Context, Editor}; -use helix_core::{ - diagnostic::DiagnosticProvider, syntax::LanguageServerFeature, - text_annotations::InlineAnnotation, Selection, Uri, -}; +use helix_core::{diagnostic::DiagnosticProvider, syntax::LanguageServerFeature, Selection, Uri}; use helix_stdx::path; -use helix_view::{ - document::{DocumentInlayHints, DocumentInlayHintsId}, - editor::Action, - handlers::lsp::SignatureHelpInvoked, - theme::Style, - Document, View, -}; +use helix_view::{editor::Action, handlers::lsp::SignatureHelpInvoked, theme::Style}; use crate::{ compositor::{self, Compositor}, @@ -1251,164 +1242,3 @@ pub fn select_references_to_symbol_under_cursor(cx: &mut Context) { }, ); } - -pub fn compute_inlay_hints_for_all_views(editor: &mut Editor, jobs: &mut crate::job::Jobs) { - if !editor.config().lsp.display_inlay_hints { - return; - } - - for (view, _) in editor.tree.views() { - let doc = match editor.documents.get(&view.doc) { - Some(doc) => doc, - None => continue, - }; - if let Some(callback) = compute_inlay_hints_for_view(view, doc) { - jobs.callback(callback); - } - } -} - -fn compute_inlay_hints_for_view( - view: &View, - doc: &Document, -) -> Option<std::pin::Pin<Box<impl Future<Output = Result<crate::job::Callback, anyhow::Error>>>>> { - let view_id = view.id; - let doc_id = view.doc; - - let language_server = doc - .language_servers_with_feature(LanguageServerFeature::InlayHints) - .next()?; - - let doc_text = doc.text(); - let len_lines = doc_text.len_lines(); - - // Compute ~3 times the current view height of inlay hints, that way some scrolling - // will not show half the view with hints and half without while still being faster - // than computing all the hints for the full file (which could be dozens of time - // longer than the view is). - let view_height = view.inner_height(); - let first_visible_line = - doc_text.char_to_line(doc.view_offset(view_id).anchor.min(doc_text.len_chars())); - let first_line = first_visible_line.saturating_sub(view_height); - let last_line = first_visible_line - .saturating_add(view_height.saturating_mul(2)) - .min(len_lines); - - let new_doc_inlay_hints_id = DocumentInlayHintsId { - first_line, - last_line, - }; - // Don't recompute the annotations in case nothing has changed about the view - if !doc.inlay_hints_oudated - && doc - .inlay_hints(view_id) - .is_some_and(|dih| dih.id == new_doc_inlay_hints_id) - { - return None; - } - - let doc_slice = doc_text.slice(..); - let first_char_in_range = doc_slice.line_to_char(first_line); - let last_char_in_range = doc_slice.line_to_char(last_line); - - let range = helix_lsp::util::range_to_lsp_range( - doc_text, - helix_core::Range::new(first_char_in_range, last_char_in_range), - language_server.offset_encoding(), - ); - - let offset_encoding = language_server.offset_encoding(); - - let callback = super::make_job_callback( - language_server.text_document_range_inlay_hints(doc.identifier(), range, None)?, - move |editor, _compositor, response: Option<Vec<lsp::InlayHint>>| { - // The config was modified or the window was closed while the request was in flight - if !editor.config().lsp.display_inlay_hints || editor.tree.try_get(view_id).is_none() { - return; - } - - // Add annotations to relevant document, not the current one (it may have changed in between) - let doc = match editor.documents.get_mut(&doc_id) { - Some(doc) => doc, - None => return, - }; - - // If we have neither hints nor an LSP, empty the inlay hints since they're now oudated - let mut hints = match response { - Some(hints) if !hints.is_empty() => hints, - _ => { - doc.set_inlay_hints( - view_id, - DocumentInlayHints::empty_with_id(new_doc_inlay_hints_id), - ); - doc.inlay_hints_oudated = false; - return; - } - }; - - // Most language servers will already send them sorted but ensure this is the case to - // avoid errors on our end. - hints.sort_by_key(|inlay_hint| inlay_hint.position); - - let mut padding_before_inlay_hints = Vec::new(); - let mut type_inlay_hints = Vec::new(); - let mut parameter_inlay_hints = Vec::new(); - let mut other_inlay_hints = Vec::new(); - let mut padding_after_inlay_hints = Vec::new(); - - let doc_text = doc.text(); - - for hint in hints { - let char_idx = - match helix_lsp::util::lsp_pos_to_pos(doc_text, hint.position, offset_encoding) - { - Some(pos) => pos, - // Skip inlay hints that have no "real" position - None => continue, - }; - - let label = match hint.label { - lsp::InlayHintLabel::String(s) => s, - lsp::InlayHintLabel::LabelParts(parts) => parts - .into_iter() - .map(|p| p.value) - .collect::<Vec<_>>() - .join(""), - }; - - let inlay_hints_vec = match hint.kind { - Some(lsp::InlayHintKind::TYPE) => &mut type_inlay_hints, - Some(lsp::InlayHintKind::PARAMETER) => &mut parameter_inlay_hints, - // We can't warn on unknown kind here since LSPs are free to set it or not, for - // example Rust Analyzer does not: every kind will be `None`. - _ => &mut other_inlay_hints, - }; - - if let Some(true) = hint.padding_left { - padding_before_inlay_hints.push(InlineAnnotation::new(char_idx, " ")); - } - - inlay_hints_vec.push(InlineAnnotation::new(char_idx, label)); - - if let Some(true) = hint.padding_right { - padding_after_inlay_hints.push(InlineAnnotation::new(char_idx, " ")); - } - } - - doc.set_inlay_hints( - view_id, - DocumentInlayHints { - id: new_doc_inlay_hints_id, - type_inlay_hints, - parameter_inlay_hints, - other_inlay_hints, - padding_before_inlay_hints, - padding_after_inlay_hints, - }, - ); - doc.inlay_hints_oudated = false; - }, - ); - - Some(callback) -} |