character: 26,
},
},
- severity: Some(
- Hint,
- ),
- code: Some(
- String(
- "E0277",
- ),
- ),
- code_description: Some(
- CodeDescription {
- href: Url {
- scheme: "https",
- username: "",
- password: None,
- host: Some(
- Domain(
- "doc.rust-lang.org",
- ),
- ),
- port: None,
- path: "/error-index.html",
- query: None,
- fragment: Some(
- "E0277",
- ),
- },
- },
- ),
- source: Some(
- "rustc",
- ),
- message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
- related_information: Some(
- [
- DiagnosticRelatedInformation {
- location: Location {
- uri: Url {
- scheme: "file",
- username: "",
- password: None,
- host: None,
- port: None,
- path: "/test/%3C::core::macros::assert_eq%20macros%3E",
- query: None,
- fragment: None,
- },
- range: Range {
- start: Position {
- line: 6,
- character: 30,
- },
- end: Position {
- line: 6,
- character: 32,
- },
- },
- },
- message: "Exact error occurred here",
- },
- ],
- ),
- tags: None,
- data: None,
- },
- fixes: [],
- },
- MappedRustDiagnostic {
- url: Url {
- scheme: "file",
- username: "",
- password: None,
- host: None,
- port: None,
- path: "/test/%3C::core::macros::assert_eq%20macros%3E",
- query: None,
- fragment: None,
- },
- diagnostic: Diagnostic {
- range: Range {
- start: Position {
- line: 6,
- character: 30,
- },
- end: Position {
- line: 6,
- character: 32,
- },
- },
severity: Some(
Error,
),
"rustc",
),
message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
- related_information: Some(
- [
- DiagnosticRelatedInformation {
- location: Location {
- uri: Url {
- scheme: "file",
- username: "",
- password: None,
- host: None,
- port: None,
- path: "/test/src/main.rs",
- query: None,
- fragment: None,
- },
- range: Range {
- start: Position {
- line: 1,
- character: 4,
- },
- end: Position {
- line: 1,
- character: 26,
- },
- },
- },
- message: "Error originated from macro call here",
- },
- ],
- ),
+ related_information: None,
tags: None,
data: None,
},
Some(res)
}
+/// Checks whether a file name is from macro invocation and does not refer to an actual file.
+fn is_dummy_macro_file(file_name: &str) -> bool {
+ // FIXME: current rustc does not seem to emit `<macro file>` files anymore?
+ file_name.starts_with('<') && file_name.ends_with('>')
+}
+
/// Converts a Rust span to a LSP location
fn location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location {
let file_name = workspace_root.join(&span.file_name);
/// workspace into account and tries to avoid those, in case macros are involved.
fn primary_location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location {
let span_stack = std::iter::successors(Some(span), |span| Some(&span.expansion.as_ref()?.span));
- for span in span_stack {
+ for span in span_stack.clone() {
let abs_path = workspace_root.join(&span.file_name);
- if abs_path.starts_with(workspace_root) {
+ if !is_dummy_macro_file(&span.file_name) && abs_path.starts_with(workspace_root) {
return location(workspace_root, span);
}
}
- location(workspace_root, span)
+ // Fall back to the outermost macro invocation if no suitable span comes up.
+ let last_span = span_stack.last().unwrap();
+ location(workspace_root, last_span)
}
/// Converts a secondary Rust span to a LSP related information
Some(&span.expansion.as_ref()?.span)
});
for (i, span) in span_stack.enumerate() {
+ if is_dummy_macro_file(&span.file_name) {
+ continue;
+ }
+
// First span is the original diagnostic, others are macro call locations that
// generated that code.
let is_in_macro_call = i != 0;