diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index 14918818d..dba134fc3 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -842,11 +842,12 @@ impl Client { &self, text_document: lsp::TextDocumentIdentifier, range: lsp::Range, + context: lsp::CodeActionContext, ) -> impl Future> { let params = lsp::CodeActionParams { text_document, range, - context: lsp::CodeActionContext::default(), + context, work_done_progress_params: lsp::WorkDoneProgressParams::default(), partial_result_params: lsp::PartialResultParams::default(), }; diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 767481367..13ac32ff9 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -58,6 +58,36 @@ pub mod util { use super::*; use helix_core::{Range, Rope, Transaction}; + /// Converts a diagnostic in the document to [`lsp::Diagnostic`]. + /// + /// Panics when [`pos_to_lsp_pos`] would for an invalid range on the diagnostic. + pub fn diagnostic_to_lsp_diagnostic( + doc: &Rope, + diag: &helix_core::diagnostic::Diagnostic, + offset_encoding: OffsetEncoding, + ) -> lsp::Diagnostic { + use helix_core::diagnostic::Severity::*; + + let range = Range::new(diag.range.start, diag.range.end); + let severity = diag.severity.map(|s| match s { + Hint => lsp::DiagnosticSeverity::HINT, + Info => lsp::DiagnosticSeverity::INFORMATION, + Warning => lsp::DiagnosticSeverity::WARNING, + Error => lsp::DiagnosticSeverity::ERROR, + }); + + // TODO: add support for Diagnostic.data + lsp::Diagnostic::new( + range_to_lsp_range(doc, range, offset_encoding), + severity, + None, + None, + diag.message.to_owned(), + None, + None, + ) + } + /// Converts [`lsp::Position`] to a position in the document. /// /// Returns `None` if position exceeds document length or an operation overflows. diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 1db57ecf2..0a12ae392 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -1,6 +1,6 @@ use helix_lsp::{ block_on, lsp, - util::{lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range}, + util::{diagnostic_to_lsp_diagnostic, lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range}, OffsetEncoding, }; @@ -192,15 +192,29 @@ pub fn code_action(cx: &mut Context) { let language_server = language_server!(cx.editor, doc); - let range = range_to_lsp_range( - doc.text(), - doc.selection(view.id).primary(), - language_server.offset_encoding(), - ); - - let future = language_server.code_actions(doc.identifier(), range); + let selection_range = doc.selection(view.id).primary(); let offset_encoding = language_server.offset_encoding(); + let range = range_to_lsp_range(doc.text(), selection_range, offset_encoding); + + let future = language_server.code_actions( + doc.identifier(), + range, + // Filter and convert overlapping diagnostics + lsp::CodeActionContext { + diagnostics: doc + .diagnostics() + .iter() + .filter(|&diag| { + selection_range + .overlaps(&helix_core::Range::new(diag.range.start, diag.range.end)) + }) + .map(|diag| diagnostic_to_lsp_diagnostic(doc.text(), diag, offset_encoding)) + .collect(), + only: None, + }, + ); + cx.callback( future, move |editor, compositor, response: Option| {