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
This commit is contained in:
parent
2eca2901f3
commit
33b7483db5
3 changed files with 54 additions and 9 deletions
|
@ -842,11 +842,12 @@ impl Client {
|
||||||
&self,
|
&self,
|
||||||
text_document: lsp::TextDocumentIdentifier,
|
text_document: lsp::TextDocumentIdentifier,
|
||||||
range: lsp::Range,
|
range: lsp::Range,
|
||||||
|
context: lsp::CodeActionContext,
|
||||||
) -> impl Future<Output = Result<Value>> {
|
) -> impl Future<Output = Result<Value>> {
|
||||||
let params = lsp::CodeActionParams {
|
let params = lsp::CodeActionParams {
|
||||||
text_document,
|
text_document,
|
||||||
range,
|
range,
|
||||||
context: lsp::CodeActionContext::default(),
|
context,
|
||||||
work_done_progress_params: lsp::WorkDoneProgressParams::default(),
|
work_done_progress_params: lsp::WorkDoneProgressParams::default(),
|
||||||
partial_result_params: lsp::PartialResultParams::default(),
|
partial_result_params: lsp::PartialResultParams::default(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,6 +58,36 @@ pub mod util {
|
||||||
use super::*;
|
use super::*;
|
||||||
use helix_core::{Range, Rope, Transaction};
|
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.
|
/// Converts [`lsp::Position`] to a position in the document.
|
||||||
///
|
///
|
||||||
/// Returns `None` if position exceeds document length or an operation overflows.
|
/// Returns `None` if position exceeds document length or an operation overflows.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use helix_lsp::{
|
use helix_lsp::{
|
||||||
block_on, 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,
|
OffsetEncoding,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,15 +192,29 @@ pub fn code_action(cx: &mut Context) {
|
||||||
|
|
||||||
let language_server = language_server!(cx.editor, doc);
|
let language_server = language_server!(cx.editor, doc);
|
||||||
|
|
||||||
let range = range_to_lsp_range(
|
let selection_range = doc.selection(view.id).primary();
|
||||||
doc.text(),
|
|
||||||
doc.selection(view.id).primary(),
|
|
||||||
language_server.offset_encoding(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let future = language_server.code_actions(doc.identifier(), range);
|
|
||||||
let offset_encoding = language_server.offset_encoding();
|
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(
|
cx.callback(
|
||||||
future,
|
future,
|
||||||
move |editor, compositor, response: Option<lsp::CodeActionResponse>| {
|
move |editor, compositor, response: Option<lsp::CodeActionResponse>| {
|
||||||
|
|
Loading…
Reference in a new issue