Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs10
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs36
-rw-r--r--crates/rust-analyzer/src/handlers.rs9
3 files changed, 32 insertions, 23 deletions
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs
index c0dab45889..56b3afce98 100644
--- a/crates/rust-analyzer/src/diagnostics.rs
+++ b/crates/rust-analyzer/src/diagnostics.rs
@@ -29,7 +29,8 @@ pub(crate) struct DiagnosticCollection {
#[derive(Debug, Clone)]
pub(crate) struct Fix {
- pub(crate) range: lsp_types::Range,
+ // Fixes may be triggerable from multiple ranges.
+ pub(crate) ranges: Vec<lsp_types::Range>,
pub(crate) action: lsp_ext::CodeAction,
}
@@ -43,7 +44,7 @@ impl DiagnosticCollection {
&mut self,
file_id: FileId,
diagnostic: lsp_types::Diagnostic,
- fix: Option<lsp_ext::CodeAction>,
+ fix: Option<Fix>,
) {
let diagnostics = self.check.entry(file_id).or_default();
for existing_diagnostic in diagnostics.iter() {
@@ -53,10 +54,7 @@ impl DiagnosticCollection {
}
let check_fixes = Arc::make_mut(&mut self.check_fixes);
- check_fixes
- .entry(file_id)
- .or_default()
- .extend(fix.into_iter().map(|action| Fix { range: diagnostic.range, action }));
+ check_fixes.entry(file_id).or_default().extend(fix);
diagnostics.push(diagnostic);
self.changes.insert(file_id);
}
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 48af9c186d..51dbc1939b 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -9,7 +9,7 @@ use vfs::{AbsPath, AbsPathBuf};
use crate::{lsp_ext, to_proto::url_from_abs_path};
-use super::DiagnosticsMapConfig;
+use super::{DiagnosticsMapConfig, Fix};
/// Determines the LSP severity from a diagnostic
fn diagnostic_severity(
@@ -114,7 +114,7 @@ fn resolve_path(
struct SubDiagnostic {
related: lsp_types::DiagnosticRelatedInformation,
- suggested_fix: Option<lsp_ext::CodeAction>,
+ suggested_fix: Option<Fix>,
}
enum MappedRustChildDiagnostic {
@@ -171,18 +171,24 @@ fn map_rust_child_diagnostic(
location: location(config, workspace_root, spans[0]),
message: message.clone(),
},
- suggested_fix: Some(lsp_ext::CodeAction {
- title: message,
- group: None,
- kind: Some(lsp_types::CodeActionKind::QUICKFIX),
- edit: Some(lsp_ext::SnippetWorkspaceEdit {
- // FIXME: there's no good reason to use edit_map here....
- changes: Some(edit_map),
- document_changes: None,
- change_annotations: None,
- }),
- is_preferred: Some(true),
- data: None,
+ suggested_fix: Some(Fix {
+ ranges: spans
+ .iter()
+ .map(|&span| location(config, workspace_root, span).range)
+ .collect(),
+ action: lsp_ext::CodeAction {
+ title: message,
+ group: None,
+ kind: Some(lsp_types::CodeActionKind::QUICKFIX),
+ edit: Some(lsp_ext::SnippetWorkspaceEdit {
+ // FIXME: there's no good reason to use edit_map here....
+ changes: Some(edit_map),
+ document_changes: None,
+ change_annotations: None,
+ }),
+ is_preferred: Some(true),
+ data: None,
+ },
}),
})
}
@@ -192,7 +198,7 @@ fn map_rust_child_diagnostic(
pub(crate) struct MappedRustDiagnostic {
pub(crate) url: lsp_types::Url,
pub(crate) diagnostic: lsp_types::Diagnostic,
- pub(crate) fix: Option<lsp_ext::CodeAction>,
+ pub(crate) fix: Option<Fix>,
}
/// Converts a Rust root diagnostic to LSP form
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index c3583df713..6bc2afc6fe 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1019,8 +1019,13 @@ pub(crate) fn handle_code_action(
for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() {
// FIXME: this mapping is awkward and shouldn't exist. Refactor
// `snap.check_fixes` to not convert to LSP prematurely.
- let fix_range = from_proto::text_range(&line_index, fix.range);
- if fix_range.intersect(frange.range).is_some() {
+ let intersect_fix_range = fix
+ .ranges
+ .iter()
+ .copied()
+ .map(|range| from_proto::text_range(&line_index, range))
+ .any(|fix_range| fix_range.intersect(frange.range).is_some());
+ if intersect_fix_range {
res.push(fix.action.clone());
}
}