aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Jadoul2022-04-17 03:05:23 +0000
committerGitHub2022-04-17 03:05:23 +0000
commit33b7483db53684cdd0a36f873662f8d6ff163201 (patch)
tree5a8323631f0b95e2030d755432893dcf57ce8b39
parent2eca2901f31083af85ffd6f299c64ad80a8bfaf5 (diff)
Send active diagnostics to LSP when requesting code actions. (#2005)
* Send active diagnostics to LSP when requesting code actions. This allows for e.g. clangd to properly send the quickfix code actions corresponding to those diagnostics as options. The LSP spec v3.16.0 introduced an opaque `data` member that would allow the server to persist arbitrary data between the diagnostic and the code actions request, but this is not supported yet by this commit. * Reuse existing range_to_lsp_range functionality
-rw-r--r--helix-lsp/src/client.rs3
-rw-r--r--helix-lsp/src/lib.rs30
-rw-r--r--helix-term/src/commands/lsp.rs30
3 files changed, 54 insertions, 9 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 14918818..dba134fc 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<Output = Result<Value>> {
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 76748136..13ac32ff 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 1db57ecf..0a12ae39 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<lsp::CodeActionResponse>| {