diff options
-rw-r--r-- | crates/rust-analyzer/src/diagnostics/to_proto.rs | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index c632630d1..89fe834f4 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs | |||
@@ -48,6 +48,22 @@ fn location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location | |||
48 | lsp_types::Location { uri, range } | 48 | lsp_types::Location { uri, range } |
49 | } | 49 | } |
50 | 50 | ||
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 | |||
51 | /// Converts a secondary Rust span to a LSP related information | 67 | /// Converts a secondary Rust span to a LSP related information |
52 | /// | 68 | /// |
53 | /// If the span is unlabelled this will return `None`. | 69 | /// If the span is unlabelled this will return `None`. |
@@ -217,7 +233,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( | |||
217 | primary_spans | 233 | primary_spans |
218 | .iter() | 234 | .iter() |
219 | .flat_map(|primary_span| { | 235 | .flat_map(|primary_span| { |
220 | let primary_location = location(workspace_root, &primary_span); | 236 | let primary_location = primary_location(workspace_root, &primary_span); |
221 | 237 | ||
222 | let mut message = message.clone(); | 238 | let mut message = message.clone(); |
223 | if needs_primary_span_label { | 239 | if needs_primary_span_label { |
@@ -235,14 +251,16 @@ pub(crate) fn map_rust_diagnostic_to_lsp( | |||
235 | // where the error originated | 251 | // where the error originated |
236 | // Also, we would generate an additional diagnostic, so that exact place of macro | 252 | // Also, we would generate an additional diagnostic, so that exact place of macro |
237 | // will be highlighted in the error origin place. | 253 | // 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| { |
239 | Some(&span.expansion.as_ref()?.span) | 255 | Some(&span.expansion.as_ref()?.span) |
240 | }) | 256 | }); |
241 | .skip(1); | 257 | for span in span_stack { |
242 | for macro_span in macro_calls { | 258 | let secondary_location = location(workspace_root, &span); |
243 | let in_macro_location = location(workspace_root, ¯o_span); | 259 | if secondary_location == primary_location { |
260 | continue; | ||
261 | } | ||
244 | related_info_macro_calls.push(lsp_types::DiagnosticRelatedInformation { | 262 | related_info_macro_calls.push(lsp_types::DiagnosticRelatedInformation { |
245 | location: in_macro_location.clone(), | 263 | location: secondary_location.clone(), |
246 | message: "Error originated from macro call here".to_string(), | 264 | message: "Error originated from macro call here".to_string(), |
247 | }); | 265 | }); |
248 | // For the additional in-macro diagnostic we add the inverse message pointing to the error location in code. | 266 | // 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( | |||
253 | }]; | 271 | }]; |
254 | 272 | ||
255 | let diagnostic = lsp_types::Diagnostic { | 273 | let diagnostic = lsp_types::Diagnostic { |
256 | range: in_macro_location.range, | 274 | range: secondary_location.range, |
257 | // downgrade to hint if we're pointing at the macro | 275 | // downgrade to hint if we're pointing at the macro |
258 | severity: Some(lsp_types::DiagnosticSeverity::Hint), | 276 | severity: Some(lsp_types::DiagnosticSeverity::Hint), |
259 | code: code.clone().map(lsp_types::NumberOrString::String), | 277 | code: code.clone().map(lsp_types::NumberOrString::String), |
@@ -265,7 +283,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( | |||
265 | data: None, | 283 | data: None, |
266 | }; | 284 | }; |
267 | diagnostics.push(MappedRustDiagnostic { | 285 | diagnostics.push(MappedRustDiagnostic { |
268 | url: in_macro_location.uri, | 286 | url: secondary_location.uri, |
269 | diagnostic, | 287 | diagnostic, |
270 | fixes: Vec::new(), | 288 | fixes: Vec::new(), |
271 | }); | 289 | }); |