Handle diagnostics with multiple primary spans

This commit is contained in:
Emil Lauridsen 2020-03-12 15:24:20 +01:00
parent 637c795b3c
commit 98e8ad5e60
11 changed files with 564 additions and 537 deletions

View file

@ -180,13 +180,13 @@ pub(crate) struct MappedRustDiagnostic {
pub(crate) fn map_rust_diagnostic_to_lsp(
rd: &RustDiagnostic,
workspace_root: &PathBuf,
) -> Option<MappedRustDiagnostic> {
let primary_span = rd.spans.iter().find(|s| s.is_primary)?;
let location = map_span_to_location(&primary_span, workspace_root);
) -> Vec<MappedRustDiagnostic> {
let primary_spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
if primary_spans.is_empty() {
return vec![];
}
let severity = map_level_to_severity(rd.level);
let mut primary_span_label = primary_span.label.as_ref();
let mut source = String::from("rustc");
let mut code = rd.code.as_ref().map(|c| c.code.clone());
@ -199,19 +199,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
}
}
let mut needs_primary_span_label = true;
let mut related_information = vec![];
let mut tags = vec![];
// If error occurs from macro expansion, add related info pointing to
// where the error originated
if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
related_information.push(DiagnosticRelatedInformation {
location: def_loc,
message: "Error originated from macro here".to_string(),
});
}
for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
let related = map_secondary_span_to_related(secondary_span, workspace_root);
if let Some(related) = related {
@ -231,15 +222,11 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
// These secondary messages usually duplicate the content of the
// primary span label.
primary_span_label = None;
needs_primary_span_label = false;
}
}
}
if let Some(primary_span_label) = primary_span_label {
write!(&mut message, "\n{}", primary_span_label).unwrap();
}
if is_unused_or_unnecessary(rd) {
tags.push(DiagnosticTag::Unnecessary);
}
@ -248,21 +235,45 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
tags.push(DiagnosticTag::Deprecated);
}
primary_spans
.iter()
.map(|primary_span| {
let location = map_span_to_location(&primary_span, workspace_root);
let mut message = message.clone();
if needs_primary_span_label {
if let Some(primary_span_label) = &primary_span.label {
write!(&mut message, "\n{}", primary_span_label).unwrap();
}
}
// If error occurs from macro expansion, add related info pointing to
// where the error originated
if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
related_information.push(DiagnosticRelatedInformation {
location: def_loc,
message: "Error originated from macro here".to_string(),
});
}
let diagnostic = Diagnostic {
range: location.range,
severity,
code: code.map(NumberOrString::String),
source: Some(source),
code: code.clone().map(NumberOrString::String),
source: Some(source.clone()),
message,
related_information: if !related_information.is_empty() {
Some(related_information)
Some(related_information.clone())
} else {
None
},
tags: if !tags.is_empty() { Some(tags) } else { None },
tags: if !tags.is_empty() { Some(tags.clone()) } else { None },
};
Some(MappedRustDiagnostic { location, diagnostic, fixes })
MappedRustDiagnostic { location, diagnostic, fixes: fixes.clone() }
})
.collect()
}
/// Returns a `Url` object from a given path, will lowercase drive letters if present.

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/mir/tagset.rs",
@ -96,4 +97,5 @@ MappedRustDiagnostic {
is_preferred: None,
},
],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/src/main.rs",
@ -43,4 +44,5 @@ MappedRustDiagnostic {
tags: None,
},
fixes: [],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/crates/ra_hir_def/src/data.rs",
@ -58,4 +59,5 @@ MappedRustDiagnostic {
tags: None,
},
fixes: [],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/src/main.rs",
@ -109,4 +110,5 @@ MappedRustDiagnostic {
is_preferred: None,
},
],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/ty/list_iter.rs",
@ -43,4 +44,5 @@ MappedRustDiagnostic {
tags: None,
},
fixes: [],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/runtime/compiler_support.rs",
@ -43,4 +44,5 @@ MappedRustDiagnostic {
tags: None,
},
fixes: [],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/driver/subcommand/repl.rs",
@ -81,4 +82,5 @@ MappedRustDiagnostic {
is_preferred: None,
},
],
}
},
]

View file

@ -2,6 +2,7 @@
source: crates/ra_cargo_watch/src/conv/test.rs
expression: diag
---
[
MappedRustDiagnostic {
location: Location {
uri: "file:///test/compiler/ty/select.rs",
@ -62,4 +63,5 @@ MappedRustDiagnostic {
tags: None,
},
fixes: [],
}
},
]

View file

@ -58,7 +58,7 @@ fn snap_rustc_incompatible_type_for_trait() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -141,7 +141,7 @@ fn snap_rustc_unused_variable() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -266,7 +266,7 @@ fn snap_rustc_wrong_number_of_parameters() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -387,7 +387,7 @@ fn snap_clippy_pass_by_ref() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -431,7 +431,7 @@ fn snap_rustc_mismatched_type() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -703,7 +703,7 @@ fn snap_handles_macro_location() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -933,7 +933,7 @@ fn snap_macro_compiler_error() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}
@ -1067,6 +1067,6 @@ fn snap_multi_line_fix() {
);
let workspace_root = PathBuf::from("/test/");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic");
let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
insta::assert_debug_snapshot!(diag);
}

View file

@ -197,13 +197,12 @@ impl CheckWatcherThread {
}
CheckEvent::Msg(Message::CompilerMessage(msg)) => {
let map_result =
match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) {
Some(map_result) => map_result,
None => return,
};
let map_result = map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root);
if map_result.is_empty() {
return;
}
let MappedRustDiagnostic { location, diagnostic, fixes } = map_result;
for MappedRustDiagnostic { location, diagnostic, fixes } in map_result {
let fixes = fixes
.into_iter()
.map(|fix| {
@ -215,6 +214,7 @@ impl CheckWatcherThread {
.send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes })
.unwrap();
}
}
CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
CheckEvent::Msg(Message::Unknown) => {}