aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-03-31 16:50:19 +0100
committerJonas Schievink <[email protected]>2021-03-31 16:50:19 +0100
commit7c87e49638f6c4319cb9da3a59f87ca8e441c00d (patch)
tree5f5706e0a8f3bd295d706987a3009c0d785b9b43 /crates
parent7723dd090913de991ea258bfd5b3f6c428591235 (diff)
Search for a suitable primary location
Diffstat (limited to 'crates')
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs36
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.
55fn 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, &macro_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 });