@@ -48,6 +48,22 @@ fn location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location
48
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
67
/// Converts a secondary Rust span to a LSP related information
52
68
///
53
69
/// If the span is unlabelled this will return `None`.
@@ -217,7 +233,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
217
233
primary_spans
218
234
. iter ( )
219
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
238
let mut message = message. clone ( ) ;
223
239
if needs_primary_span_label {
@@ -235,14 +251,16 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
235
251
// where the error originated
236
252
// Also, we would generate an additional diagnostic, so that exact place of macro
237
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
255
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
+ }
244
262
related_info_macro_calls. push ( lsp_types:: DiagnosticRelatedInformation {
245
- location : in_macro_location . clone ( ) ,
263
+ location : secondary_location . clone ( ) ,
246
264
message : "Error originated from macro call here" . to_string ( ) ,
247
265
} ) ;
248
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
273
let diagnostic = lsp_types:: Diagnostic {
256
- range : in_macro_location . range ,
274
+ range : secondary_location . range ,
257
275
// downgrade to hint if we're pointing at the macro
258
276
severity : Some ( lsp_types:: DiagnosticSeverity :: Hint ) ,
259
277
code : code. clone ( ) . map ( lsp_types:: NumberOrString :: String ) ,
@@ -265,7 +283,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
265
283
data : None ,
266
284
} ;
267
285
diagnostics. push ( MappedRustDiagnostic {
268
- url : in_macro_location . uri ,
286
+ url : secondary_location . uri ,
269
287
diagnostic,
270
288
fixes : Vec :: new ( ) ,
271
289
} ) ;
0 commit comments