Skip to content

Commit 7c87e49

Browse files
author
Jonas Schievink
committed
Search for a suitable primary location
1 parent 7723dd0 commit 7c87e49

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

crates/rust-analyzer/src/diagnostics/to_proto.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ fn location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location
4848
lsp_types::Location { uri, range }
4949
}
5050

51+
/// Extracts a suitable "primary" location from a rustc diagnostic.
52+
///
53+
/// This takes locations pointing into the standard library, or generally outside the current
54+
/// workspace into account and tries to avoid those, in case macros are involved.
55+
fn primary_location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location {
56+
let span_stack = std::iter::successors(Some(span), |span| Some(&span.expansion.as_ref()?.span));
57+
for span in span_stack {
58+
let abs_path = workspace_root.join(&span.file_name);
59+
if abs_path.starts_with(workspace_root) {
60+
return location(workspace_root, span);
61+
}
62+
}
63+
64+
location(workspace_root, span)
65+
}
66+
5167
/// Converts a secondary Rust span to a LSP related information
5268
///
5369
/// If the span is unlabelled this will return `None`.
@@ -217,7 +233,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
217233
primary_spans
218234
.iter()
219235
.flat_map(|primary_span| {
220-
let primary_location = location(workspace_root, &primary_span);
236+
let primary_location = primary_location(workspace_root, &primary_span);
221237

222238
let mut message = message.clone();
223239
if needs_primary_span_label {
@@ -235,14 +251,16 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
235251
// where the error originated
236252
// Also, we would generate an additional diagnostic, so that exact place of macro
237253
// will be highlighted in the error origin place.
238-
let macro_calls = std::iter::successors(Some(*primary_span), |span| {
254+
let span_stack = std::iter::successors(Some(*primary_span), |span| {
239255
Some(&span.expansion.as_ref()?.span)
240-
})
241-
.skip(1);
242-
for macro_span in macro_calls {
243-
let in_macro_location = location(workspace_root, &macro_span);
256+
});
257+
for span in span_stack {
258+
let secondary_location = location(workspace_root, &span);
259+
if secondary_location == primary_location {
260+
continue;
261+
}
244262
related_info_macro_calls.push(lsp_types::DiagnosticRelatedInformation {
245-
location: in_macro_location.clone(),
263+
location: secondary_location.clone(),
246264
message: "Error originated from macro call here".to_string(),
247265
});
248266
// For the additional in-macro diagnostic we add the inverse message pointing to the error location in code.
@@ -253,7 +271,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
253271
}];
254272

255273
let diagnostic = lsp_types::Diagnostic {
256-
range: in_macro_location.range,
274+
range: secondary_location.range,
257275
// downgrade to hint if we're pointing at the macro
258276
severity: Some(lsp_types::DiagnosticSeverity::Hint),
259277
code: code.clone().map(lsp_types::NumberOrString::String),
@@ -265,7 +283,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
265283
data: None,
266284
};
267285
diagnostics.push(MappedRustDiagnostic {
268-
url: in_macro_location.uri,
286+
url: secondary_location.uri,
269287
diagnostic,
270288
fixes: Vec::new(),
271289
});

0 commit comments

Comments
 (0)