mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-17 02:08:30 +00:00
Merge #5282
5282: Move diagnostics tests to expect r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
f1d084fbd9
20 changed files with 202 additions and 409 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1435,9 +1435,9 @@ dependencies = [
|
|||
"anyhow",
|
||||
"crossbeam-channel",
|
||||
"env_logger",
|
||||
"expect",
|
||||
"flycheck",
|
||||
"globset",
|
||||
"insta",
|
||||
"itertools",
|
||||
"jod-thread",
|
||||
"log",
|
||||
|
|
|
@ -121,6 +121,10 @@ impl ExpectFile {
|
|||
}
|
||||
Runtime::fail_file(self, &expected, actual);
|
||||
}
|
||||
pub fn assert_debug_eq(&self, actual: &impl fmt::Debug) {
|
||||
let actual = format!("{:#?}\n", actual);
|
||||
self.assert_eq(&actual)
|
||||
}
|
||||
fn read(&self) -> String {
|
||||
fs::read_to_string(self.abs_path()).unwrap_or_default().replace("\r\n", "\n")
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ use std::{
|
|||
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
|
||||
|
||||
pub use cargo_metadata::diagnostic::{
|
||||
Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion,
|
||||
Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
|
||||
DiagnosticSpanMacroExpansion,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
|
@ -491,7 +491,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
let mut completions = get_all_completion_items(ra_fixture, &CompletionConfig::default());
|
||||
let mut completions = get_all_completion_items(CompletionConfig::default(), ra_fixture);
|
||||
completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
|
||||
let actual = completions
|
||||
.into_iter()
|
||||
|
@ -835,6 +835,7 @@ fn bar(s: &S) {
|
|||
fn suppress_arg_snippets() {
|
||||
mark::check!(suppress_arg_snippets);
|
||||
check_edit_with_config(
|
||||
CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
|
||||
"with_args",
|
||||
r#"
|
||||
fn with_args(x: i32, y: String) {}
|
||||
|
@ -844,7 +845,6 @@ fn main() { with_<|> }
|
|||
fn with_args(x: i32, y: String) {}
|
||||
fn main() { with_args($0) }
|
||||
"#,
|
||||
&CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,15 @@ use crate::{
|
|||
};
|
||||
|
||||
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
||||
do_completion_with_config(code, kind, &CompletionConfig::default())
|
||||
do_completion_with_config(CompletionConfig::default(), code, kind)
|
||||
}
|
||||
|
||||
pub(crate) fn do_completion_with_config(
|
||||
config: CompletionConfig,
|
||||
code: &str,
|
||||
kind: CompletionKind,
|
||||
config: &CompletionConfig,
|
||||
) -> Vec<CompletionItem> {
|
||||
let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config)
|
||||
let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code)
|
||||
.into_iter()
|
||||
.filter(|c| c.completion_kind == kind)
|
||||
.collect();
|
||||
|
@ -30,15 +30,15 @@ pub(crate) fn do_completion_with_config(
|
|||
}
|
||||
|
||||
pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
|
||||
completion_list_with_config(code, kind, &CompletionConfig::default())
|
||||
completion_list_with_config(CompletionConfig::default(), code, kind)
|
||||
}
|
||||
|
||||
pub(crate) fn completion_list_with_config(
|
||||
config: CompletionConfig,
|
||||
code: &str,
|
||||
kind: CompletionKind,
|
||||
config: &CompletionConfig,
|
||||
) -> String {
|
||||
let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config)
|
||||
let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(config, code)
|
||||
.into_iter()
|
||||
.filter(|c| c.completion_kind == kind)
|
||||
.collect();
|
||||
|
@ -70,19 +70,19 @@ fn monospace_width(s: &str) -> usize {
|
|||
}
|
||||
|
||||
pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
|
||||
check_edit_with_config(what, ra_fixture_before, ra_fixture_after, &CompletionConfig::default())
|
||||
check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after)
|
||||
}
|
||||
|
||||
pub(crate) fn check_edit_with_config(
|
||||
config: CompletionConfig,
|
||||
what: &str,
|
||||
ra_fixture_before: &str,
|
||||
ra_fixture_after: &str,
|
||||
config: &CompletionConfig,
|
||||
) {
|
||||
let ra_fixture_after = trim_indent(ra_fixture_after);
|
||||
let (analysis, position) = analysis_and_position(ra_fixture_before);
|
||||
let completions: Vec<CompletionItem> =
|
||||
analysis.completions(config, position).unwrap().unwrap().into();
|
||||
analysis.completions(&config, position).unwrap().unwrap().into();
|
||||
let (completion,) = completions
|
||||
.iter()
|
||||
.filter(|it| it.lookup() == what)
|
||||
|
@ -106,9 +106,9 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
|
|||
}
|
||||
|
||||
pub(crate) fn get_all_completion_items(
|
||||
config: CompletionConfig,
|
||||
code: &str,
|
||||
options: &CompletionConfig,
|
||||
) -> Vec<CompletionItem> {
|
||||
let (analysis, position) = analysis_and_position(code);
|
||||
analysis.completions(options, position).unwrap().unwrap().into()
|
||||
analysis.completions(&config, position).unwrap().unwrap().into()
|
||||
}
|
||||
|
|
|
@ -351,10 +351,10 @@ mod tests {
|
|||
use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file};
|
||||
|
||||
fn check(ra_fixture: &str) {
|
||||
check_with_config(ra_fixture, InlayHintsConfig::default());
|
||||
check_with_config(InlayHintsConfig::default(), ra_fixture);
|
||||
}
|
||||
|
||||
fn check_with_config(ra_fixture: &str, config: InlayHintsConfig) {
|
||||
fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) {
|
||||
let (analysis, file_id) = single_file(ra_fixture);
|
||||
let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
|
||||
let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
|
||||
|
@ -363,7 +363,7 @@ mod tests {
|
|||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
fn check_expect(ra_fixture: &str, config: InlayHintsConfig, expect: Expect) {
|
||||
fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) {
|
||||
let (analysis, file_id) = single_file(ra_fixture);
|
||||
let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
|
||||
expect.assert_debug_eq(&inlay_hints)
|
||||
|
@ -372,6 +372,12 @@ mod tests {
|
|||
#[test]
|
||||
fn param_hints_only() {
|
||||
check_with_config(
|
||||
InlayHintsConfig {
|
||||
parameter_hints: true,
|
||||
type_hints: false,
|
||||
chaining_hints: false,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||
fn main() {
|
||||
|
@ -382,47 +388,41 @@ fn main() {
|
|||
//^ b
|
||||
);
|
||||
}"#,
|
||||
InlayHintsConfig {
|
||||
parameter_hints: true,
|
||||
type_hints: false,
|
||||
chaining_hints: false,
|
||||
max_length: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hints_disabled() {
|
||||
check_with_config(
|
||||
r#"
|
||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||
fn main() {
|
||||
let _x = foo(4, 4);
|
||||
}"#,
|
||||
InlayHintsConfig {
|
||||
type_hints: false,
|
||||
parameter_hints: false,
|
||||
chaining_hints: false,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||
fn main() {
|
||||
let _x = foo(4, 4);
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_hints_only() {
|
||||
check_with_config(
|
||||
r#"
|
||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||
fn main() {
|
||||
let _x = foo(4, 4);
|
||||
//^^ i32
|
||||
}"#,
|
||||
InlayHintsConfig {
|
||||
type_hints: true,
|
||||
parameter_hints: false,
|
||||
chaining_hints: false,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
fn foo(a: i32, b: i32) -> i32 { a + b }
|
||||
fn main() {
|
||||
let _x = foo(4, 4);
|
||||
//^^ i32
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -590,6 +590,7 @@ fn main() {
|
|||
#[test]
|
||||
fn hint_truncation() {
|
||||
check_with_config(
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
r#"
|
||||
struct Smol<T>(T);
|
||||
|
||||
|
@ -603,7 +604,6 @@ fn main() {
|
|||
let c = Smol(Smol(0u32))
|
||||
//^ Smol<Smol<…>>
|
||||
}"#,
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -673,6 +673,7 @@ fn main() {
|
|||
#[test]
|
||||
fn omitted_parameters_hints_heuristics() {
|
||||
check_with_config(
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
r#"
|
||||
fn map(f: i32) {}
|
||||
fn filter(predicate: i32) {}
|
||||
|
@ -753,13 +754,13 @@ fn main() {
|
|||
let _: f64 = a.div_euclid(b);
|
||||
let _: f64 = a.abs_sub(b);
|
||||
}"#,
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_structs_have_no_type_hints() {
|
||||
check_with_config(
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
r#"
|
||||
enum Result<T, E> { Ok(T), Err(E) }
|
||||
use Result::*;
|
||||
|
@ -772,13 +773,18 @@ fn main() {
|
|||
Err(SyntheticSyntax) => (),
|
||||
}
|
||||
}"#,
|
||||
InlayHintsConfig { max_length: Some(8), ..Default::default() },
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chaining_hints_ignore_comments() {
|
||||
check_expect(
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
struct A(B);
|
||||
impl A { fn into_b(self) -> B { self.0 } }
|
||||
|
@ -792,12 +798,6 @@ fn main() {
|
|||
.into_c();
|
||||
}
|
||||
"#,
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
expect![[r#"
|
||||
[
|
||||
InlayHint {
|
||||
|
@ -818,6 +818,12 @@ fn main() {
|
|||
#[test]
|
||||
fn chaining_hints_without_newlines() {
|
||||
check_with_config(
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
struct A(B);
|
||||
impl A { fn into_b(self) -> B { self.0 } }
|
||||
|
@ -828,18 +834,18 @@ struct C;
|
|||
fn main() {
|
||||
let c = A(B(C)).into_b().into_c();
|
||||
}"#,
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_access_chaining_hints() {
|
||||
check_expect(
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
struct A { pub b: B }
|
||||
struct B { pub c: C }
|
||||
|
@ -858,12 +864,6 @@ fn main() {
|
|||
let x = D
|
||||
.foo();
|
||||
}"#,
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
expect![[r#"
|
||||
[
|
||||
InlayHint {
|
||||
|
@ -884,6 +884,12 @@ fn main() {
|
|||
#[test]
|
||||
fn generic_chaining_hints() {
|
||||
check_expect(
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
r#"
|
||||
struct A<T>(T);
|
||||
struct B<T>(T);
|
||||
|
@ -903,12 +909,6 @@ fn main() {
|
|||
.into_c();
|
||||
}
|
||||
"#,
|
||||
InlayHintsConfig {
|
||||
parameter_hints: false,
|
||||
type_hints: false,
|
||||
chaining_hints: true,
|
||||
max_length: None,
|
||||
},
|
||||
expect![[r#"
|
||||
[
|
||||
InlayHint {
|
||||
|
|
|
@ -58,7 +58,7 @@ winapi = "0.3.8"
|
|||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
insta = "0.16.0"
|
||||
expect = { path = "../expect" }
|
||||
test_utils = { path = "../test_utils" }
|
||||
mbe = { path = "../ra_mbe", package = "ra_mbe" }
|
||||
tt = { path = "../ra_tt", package = "ra_tt" }
|
||||
|
|
|
@ -18,7 +18,9 @@ pub struct DiagnosticsConfig {
|
|||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(crate) struct DiagnosticCollection {
|
||||
// FIXME: should be FxHashMap<FileId, Vec<ra_id::Diagnostic>>
|
||||
pub(crate) native: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
|
||||
// FIXME: should be Vec<flycheck::Diagnostic>
|
||||
pub(crate) check: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
|
||||
pub(crate) check_fixes: CheckFixes,
|
||||
changes: FxHashSet<FileId>,
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
//! `cargo check` json format to the LSP diagnostic format.
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion};
|
||||
use lsp_types::{
|
||||
Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location,
|
||||
NumberOrString, Position, Range, TextEdit, Url,
|
||||
};
|
||||
use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan};
|
||||
use stdx::format_to;
|
||||
|
||||
use crate::{lsp_ext, to_proto::url_from_abs_path};
|
||||
|
@ -14,22 +10,25 @@ use crate::{lsp_ext, to_proto::url_from_abs_path};
|
|||
use super::DiagnosticsConfig;
|
||||
|
||||
/// Determines the LSP severity from a diagnostic
|
||||
fn map_diagnostic_to_severity(
|
||||
fn diagnostic_severity(
|
||||
config: &DiagnosticsConfig,
|
||||
val: &flycheck::Diagnostic,
|
||||
) -> Option<DiagnosticSeverity> {
|
||||
let res = match val.level {
|
||||
DiagnosticLevel::Ice => DiagnosticSeverity::Error,
|
||||
DiagnosticLevel::Error => DiagnosticSeverity::Error,
|
||||
DiagnosticLevel::Warning => match &val.code {
|
||||
Some(code) if config.warnings_as_hint.contains(&code.code) => DiagnosticSeverity::Hint,
|
||||
Some(code) if config.warnings_as_info.contains(&code.code) => {
|
||||
DiagnosticSeverity::Information
|
||||
level: flycheck::DiagnosticLevel,
|
||||
code: Option<flycheck::DiagnosticCode>,
|
||||
) -> Option<lsp_types::DiagnosticSeverity> {
|
||||
let res = match level {
|
||||
DiagnosticLevel::Ice => lsp_types::DiagnosticSeverity::Error,
|
||||
DiagnosticLevel::Error => lsp_types::DiagnosticSeverity::Error,
|
||||
DiagnosticLevel::Warning => match &code {
|
||||
Some(code) if config.warnings_as_hint.contains(&code.code) => {
|
||||
lsp_types::DiagnosticSeverity::Hint
|
||||
}
|
||||
_ => DiagnosticSeverity::Warning,
|
||||
Some(code) if config.warnings_as_info.contains(&code.code) => {
|
||||
lsp_types::DiagnosticSeverity::Information
|
||||
}
|
||||
_ => lsp_types::DiagnosticSeverity::Warning,
|
||||
},
|
||||
DiagnosticLevel::Note => DiagnosticSeverity::Information,
|
||||
DiagnosticLevel::Help => DiagnosticSeverity::Hint,
|
||||
DiagnosticLevel::Note => lsp_types::DiagnosticSeverity::Information,
|
||||
DiagnosticLevel::Help => lsp_types::DiagnosticSeverity::Hint,
|
||||
DiagnosticLevel::Unknown => return None,
|
||||
};
|
||||
Some(res)
|
||||
|
@ -40,90 +39,50 @@ fn is_from_macro(file_name: &str) -> bool {
|
|||
file_name.starts_with('<') && file_name.ends_with('>')
|
||||
}
|
||||
|
||||
/// Converts a Rust macro span to a LSP location recursively
|
||||
fn map_macro_span_to_location(
|
||||
span_macro: &DiagnosticSpanMacroExpansion,
|
||||
workspace_root: &Path,
|
||||
) -> Option<Location> {
|
||||
if !is_from_macro(&span_macro.span.file_name) {
|
||||
return Some(map_span_to_location(&span_macro.span, workspace_root));
|
||||
}
|
||||
|
||||
if let Some(expansion) = &span_macro.span.expansion {
|
||||
return map_macro_span_to_location(&expansion, workspace_root);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Converts a Rust span to a LSP location, resolving macro expansion site if neccesary
|
||||
fn map_span_to_location(span: &DiagnosticSpan, workspace_root: &Path) -> Location {
|
||||
if span.expansion.is_some() {
|
||||
let expansion = span.expansion.as_ref().unwrap();
|
||||
if let Some(macro_range) = map_macro_span_to_location(&expansion, workspace_root) {
|
||||
return macro_range;
|
||||
}
|
||||
fn location(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location {
|
||||
let mut span = span.clone();
|
||||
while let Some(expansion) = span.expansion {
|
||||
span = expansion.span;
|
||||
}
|
||||
|
||||
map_span_to_location_naive(span, workspace_root)
|
||||
return location_naive(workspace_root, &span);
|
||||
}
|
||||
|
||||
/// Converts a Rust span to a LSP location
|
||||
fn map_span_to_location_naive(span: &DiagnosticSpan, workspace_root: &Path) -> Location {
|
||||
let mut file_name = workspace_root.to_path_buf();
|
||||
file_name.push(&span.file_name);
|
||||
fn location_naive(workspace_root: &Path, span: &DiagnosticSpan) -> lsp_types::Location {
|
||||
let file_name = workspace_root.join(&span.file_name);
|
||||
let uri = url_from_abs_path(&file_name);
|
||||
|
||||
// FIXME: this doesn't handle UTF16 offsets correctly
|
||||
let range = Range::new(
|
||||
Position::new(span.line_start as u64 - 1, span.column_start as u64 - 1),
|
||||
Position::new(span.line_end as u64 - 1, span.column_end as u64 - 1),
|
||||
let range = lsp_types::Range::new(
|
||||
lsp_types::Position::new(span.line_start as u64 - 1, span.column_start as u64 - 1),
|
||||
lsp_types::Position::new(span.line_end as u64 - 1, span.column_end as u64 - 1),
|
||||
);
|
||||
|
||||
Location { uri, range }
|
||||
lsp_types::Location { uri, range }
|
||||
}
|
||||
|
||||
/// Converts a secondary Rust span to a LSP related information
|
||||
/// Converts a secondary Rust span to a LSP related inflocation(ormation
|
||||
///
|
||||
/// If the span is unlabelled this will return `None`.
|
||||
fn map_secondary_span_to_related(
|
||||
span: &DiagnosticSpan,
|
||||
fn diagnostic_related_information(
|
||||
workspace_root: &Path,
|
||||
) -> Option<DiagnosticRelatedInformation> {
|
||||
span: &DiagnosticSpan,
|
||||
) -> Option<lsp_types::DiagnosticRelatedInformation> {
|
||||
let message = span.label.clone()?;
|
||||
let location = map_span_to_location(span, workspace_root);
|
||||
Some(DiagnosticRelatedInformation { location, message })
|
||||
}
|
||||
|
||||
/// Determines if diagnostic is related to unused code
|
||||
fn is_unused_or_unnecessary(rd: &flycheck::Diagnostic) -> bool {
|
||||
match &rd.code {
|
||||
Some(code) => match code.code.as_str() {
|
||||
"dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes"
|
||||
| "unused_imports" | "unused_macros" | "unused_variables" => true,
|
||||
_ => false,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if diagnostic is related to deprecated code
|
||||
fn is_deprecated(rd: &flycheck::Diagnostic) -> bool {
|
||||
match &rd.code {
|
||||
Some(code) => code.code.as_str() == "deprecated",
|
||||
None => false,
|
||||
}
|
||||
let location = location(workspace_root, span);
|
||||
Some(lsp_types::DiagnosticRelatedInformation { location, message })
|
||||
}
|
||||
|
||||
enum MappedRustChildDiagnostic {
|
||||
Related(DiagnosticRelatedInformation),
|
||||
Related(lsp_types::DiagnosticRelatedInformation),
|
||||
SuggestedFix(lsp_ext::CodeAction),
|
||||
MessageLine(String),
|
||||
}
|
||||
|
||||
fn map_rust_child_diagnostic(
|
||||
rd: &flycheck::Diagnostic,
|
||||
workspace_root: &Path,
|
||||
rd: &flycheck::Diagnostic,
|
||||
) -> MappedRustChildDiagnostic {
|
||||
let spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
|
||||
if spans.is_empty() {
|
||||
|
@ -132,21 +91,20 @@ fn map_rust_child_diagnostic(
|
|||
return MappedRustChildDiagnostic::MessageLine(rd.message.clone());
|
||||
}
|
||||
|
||||
let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new();
|
||||
let mut edit_map: HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>> = HashMap::new();
|
||||
for &span in &spans {
|
||||
match (&span.suggestion_applicability, &span.suggested_replacement) {
|
||||
(Some(Applicability::MachineApplicable), Some(suggested_replacement)) => {
|
||||
let location = map_span_to_location(span, workspace_root);
|
||||
let edit = TextEdit::new(location.range, suggested_replacement.clone());
|
||||
edit_map.entry(location.uri).or_default().push(edit);
|
||||
}
|
||||
_ => {}
|
||||
if let (Some(Applicability::MachineApplicable), Some(suggested_replacement)) =
|
||||
(&span.suggestion_applicability, &span.suggested_replacement)
|
||||
{
|
||||
let location = location(workspace_root, span);
|
||||
let edit = lsp_types::TextEdit::new(location.range, suggested_replacement.clone());
|
||||
edit_map.entry(location.uri).or_default().push(edit);
|
||||
}
|
||||
}
|
||||
|
||||
if edit_map.is_empty() {
|
||||
MappedRustChildDiagnostic::Related(DiagnosticRelatedInformation {
|
||||
location: map_span_to_location(spans[0], workspace_root),
|
||||
MappedRustChildDiagnostic::Related(lsp_types::DiagnosticRelatedInformation {
|
||||
location: location(workspace_root, spans[0]),
|
||||
message: rd.message.clone(),
|
||||
})
|
||||
} else {
|
||||
|
@ -167,8 +125,8 @@ fn map_rust_child_diagnostic(
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MappedRustDiagnostic {
|
||||
pub(crate) location: Location,
|
||||
pub(crate) diagnostic: Diagnostic,
|
||||
pub(crate) url: lsp_types::Url,
|
||||
pub(crate) diagnostic: lsp_types::Diagnostic,
|
||||
pub(crate) fixes: Vec<lsp_ext::CodeAction>,
|
||||
}
|
||||
|
||||
|
@ -192,7 +150,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
return Vec::new();
|
||||
}
|
||||
|
||||
let severity = map_diagnostic_to_severity(config, rd);
|
||||
let severity = diagnostic_severity(config, rd.level.clone(), rd.code.clone());
|
||||
|
||||
let mut source = String::from("rustc");
|
||||
let mut code = rd.code.as_ref().map(|c| c.code.clone());
|
||||
|
@ -210,7 +168,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
let mut tags = Vec::new();
|
||||
|
||||
for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
|
||||
let related = map_secondary_span_to_related(secondary_span, workspace_root);
|
||||
let related = diagnostic_related_information(workspace_root, secondary_span);
|
||||
if let Some(related) = related {
|
||||
related_information.push(related);
|
||||
}
|
||||
|
@ -219,7 +177,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
let mut fixes = Vec::new();
|
||||
let mut message = rd.message.clone();
|
||||
for child in &rd.children {
|
||||
let child = map_rust_child_diagnostic(&child, workspace_root);
|
||||
let child = map_rust_child_diagnostic(workspace_root, &child);
|
||||
match child {
|
||||
MappedRustChildDiagnostic::Related(related) => related_information.push(related),
|
||||
MappedRustChildDiagnostic::SuggestedFix(code_action) => fixes.push(code_action),
|
||||
|
@ -233,18 +191,30 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
}
|
||||
}
|
||||
|
||||
if is_unused_or_unnecessary(rd) {
|
||||
tags.push(DiagnosticTag::Unnecessary);
|
||||
}
|
||||
if let Some(code) = &rd.code {
|
||||
let code = code.code.as_str();
|
||||
if matches!(
|
||||
code,
|
||||
"dead_code"
|
||||
| "unknown_lints"
|
||||
| "unreachable_code"
|
||||
| "unused_attributes"
|
||||
| "unused_imports"
|
||||
| "unused_macros"
|
||||
| "unused_variables"
|
||||
) {
|
||||
tags.push(lsp_types::DiagnosticTag::Unnecessary);
|
||||
}
|
||||
|
||||
if is_deprecated(rd) {
|
||||
tags.push(DiagnosticTag::Deprecated);
|
||||
if matches!(code, "deprecated") {
|
||||
tags.push(lsp_types::DiagnosticTag::Deprecated);
|
||||
}
|
||||
}
|
||||
|
||||
primary_spans
|
||||
.iter()
|
||||
.map(|primary_span| {
|
||||
let location = map_span_to_location(&primary_span, workspace_root);
|
||||
let location = location(workspace_root, &primary_span);
|
||||
|
||||
let mut message = message.clone();
|
||||
if needs_primary_span_label {
|
||||
|
@ -256,17 +226,16 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
// 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,
|
||||
related_information.push(lsp_types::DiagnosticRelatedInformation {
|
||||
location: location_naive(workspace_root, &primary_span),
|
||||
message: "Error originated from macro here".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let diagnostic = Diagnostic {
|
||||
let diagnostic = lsp_types::Diagnostic {
|
||||
range: location.range,
|
||||
severity,
|
||||
code: code.clone().map(NumberOrString::String),
|
||||
code: code.clone().map(lsp_types::NumberOrString::String),
|
||||
source: Some(source.clone()),
|
||||
message,
|
||||
related_information: if related_information.is_empty() {
|
||||
|
@ -277,7 +246,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
tags: if tags.is_empty() { None } else { Some(tags.clone()) },
|
||||
};
|
||||
|
||||
MappedRustDiagnostic { location, diagnostic, fixes: fixes.clone() }
|
||||
MappedRustDiagnostic { url: location.uri, diagnostic, fixes: fixes.clone() }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -287,13 +256,22 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn parse_diagnostic(val: &str) -> flycheck::Diagnostic {
|
||||
serde_json::from_str::<flycheck::Diagnostic>(val).unwrap()
|
||||
use expect::{expect_file, ExpectFile};
|
||||
|
||||
fn check(diagnostics_json: &str, expect: ExpectFile) {
|
||||
check_with_config(DiagnosticsConfig::default(), diagnostics_json, expect)
|
||||
}
|
||||
|
||||
fn check_with_config(config: DiagnosticsConfig, diagnostics_json: &str, expect: ExpectFile) {
|
||||
let diagnostic: flycheck::Diagnostic = serde_json::from_str(diagnostics_json).unwrap();
|
||||
let workspace_root = Path::new("/test/");
|
||||
let actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root);
|
||||
expect.assert_debug_eq(&actual)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_rustc_incompatible_type_for_trait() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_incompatible_type_for_trait() {
|
||||
check(
|
||||
r##"{
|
||||
"message": "method `next` has an incompatible type for trait",
|
||||
"code": {
|
||||
|
@ -337,16 +315,13 @@ mod tests {
|
|||
"rendered": "error[E0053]: method `next` has an incompatible type for trait\n --> compiler/ty/list_iter.rs:52:5\n |\n52 | fn next(&self) -> Option<&'list ty::Ref<M>> {\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability\n |\n = note: expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`\n\n"
|
||||
}
|
||||
"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_incompatible_type_for_trait.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_rustc_unused_variable() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_unused_variable() {
|
||||
check(
|
||||
r##"{
|
||||
"message": "unused variable: `foo`",
|
||||
"code": {
|
||||
|
@ -419,17 +394,18 @@ mod tests {
|
|||
],
|
||||
"rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_unused_variable.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn snap_rustc_unused_variable_as_info() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_unused_variable_as_info() {
|
||||
check_with_config(
|
||||
DiagnosticsConfig {
|
||||
warnings_as_info: vec!["unused_variables".to_string()],
|
||||
..DiagnosticsConfig::default()
|
||||
},
|
||||
r##"{
|
||||
"message": "unused variable: `foo`",
|
||||
"code": {
|
||||
|
@ -502,22 +478,18 @@ mod tests {
|
|||
],
|
||||
"rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_unused_variable_as_info.txt"],
|
||||
);
|
||||
|
||||
let config = DiagnosticsConfig {
|
||||
warnings_as_info: vec!["unused_variables".to_string()],
|
||||
..DiagnosticsConfig::default()
|
||||
};
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn snap_rustc_unused_variable_as_hint() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_unused_variable_as_hint() {
|
||||
check_with_config(
|
||||
DiagnosticsConfig {
|
||||
warnings_as_hint: vec!["unused_variables".to_string()],
|
||||
..DiagnosticsConfig::default()
|
||||
},
|
||||
r##"{
|
||||
"message": "unused variable: `foo`",
|
||||
"code": {
|
||||
|
@ -590,21 +562,13 @@ mod tests {
|
|||
],
|
||||
"rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_unused_variable_as_hint.txt"],
|
||||
);
|
||||
|
||||
let config = DiagnosticsConfig {
|
||||
warnings_as_hint: vec!["unused_variables".to_string()],
|
||||
..DiagnosticsConfig::default()
|
||||
};
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_rustc_wrong_number_of_parameters() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_wrong_number_of_parameters() {
|
||||
check(
|
||||
r##"{
|
||||
"message": "this function takes 2 parameters but 3 parameters were supplied",
|
||||
"code": {
|
||||
|
@ -719,16 +683,13 @@ mod tests {
|
|||
"children": [],
|
||||
"rendered": "error[E0061]: this function takes 2 parameters but 3 parameters were supplied\n --> compiler/ty/select.rs:104:18\n |\n104 | self.add_evidence(target_fixed, evidence_fixed, false);\n | ^^^^^^^^^^^^ expected 2 parameters\n...\n219 | / pub fn add_evidence(\n220 | | &mut self,\n221 | | target_poly: &ty::Ref<ty::Poly>,\n222 | | evidence_poly: &ty::Ref<ty::Poly>,\n... |\n230 | | }\n231 | | }\n | |_____- defined here\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_wrong_number_of_parameters.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_clippy_pass_by_ref() {
|
||||
let diag = parse_diagnostic(
|
||||
fn clippy_pass_by_ref() {
|
||||
check(
|
||||
r##"{
|
||||
"message": "this argument is passed by reference, but would be more efficient if passed by value",
|
||||
"code": {
|
||||
|
@ -839,16 +800,13 @@ mod tests {
|
|||
],
|
||||
"rendered": "warning: this argument is passed by reference, but would be more efficient if passed by value\n --> compiler/mir/tagset.rs:42:24\n |\n42 | pub fn is_disjoint(&self, other: Self) -> bool {\n | ^^^^^ help: consider passing by value instead: `self`\n |\nnote: lint level defined here\n --> compiler/lib.rs:1:9\n |\n1 | #![warn(clippy::all)]\n | ^^^^^^^^^^^\n = note: #[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/clippy_pass_by_ref.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_rustc_mismatched_type() {
|
||||
let diag = parse_diagnostic(
|
||||
fn rustc_mismatched_type() {
|
||||
check(
|
||||
r##"{
|
||||
"message": "mismatched types",
|
||||
"code": {
|
||||
|
@ -882,16 +840,13 @@ mod tests {
|
|||
"children": [],
|
||||
"rendered": "error[E0308]: mismatched types\n --> runtime/compiler_support.rs:48:65\n |\n48 | let layout = alloc::Layout::from_size_align_unchecked(size, align);\n | ^^^^^ expected usize, found u32\n\n"
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/rustc_mismatched_type.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_handles_macro_location() {
|
||||
let diag = parse_diagnostic(
|
||||
fn handles_macro_location() {
|
||||
check(
|
||||
r##"{
|
||||
"rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n",
|
||||
"children": [
|
||||
|
@ -1153,16 +1108,13 @@ mod tests {
|
|||
}
|
||||
]
|
||||
}"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/handles_macro_location.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_macro_compiler_error() {
|
||||
let diag = parse_diagnostic(
|
||||
fn macro_compiler_error() {
|
||||
check(
|
||||
r##"{
|
||||
"rendered": "error: Please register your known path in the path module\n --> crates/ra_hir_def/src/path.rs:265:9\n |\n265 | compile_error!(\"Please register your known path in the path module\")\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | \n ::: crates/ra_hir_def/src/data.rs:80:16\n |\n80 | let path = path![std::future::Future];\n | -------------------------- in this macro invocation\n\n",
|
||||
"children": [],
|
||||
|
@ -1382,16 +1334,13 @@ mod tests {
|
|||
]
|
||||
}
|
||||
"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/macro_compiler_error.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snap_multi_line_fix() {
|
||||
let diag = parse_diagnostic(
|
||||
check(
|
||||
r##"{
|
||||
"rendered": "warning: returning the result of a let binding from a block\n --> src/main.rs:4:5\n |\n3 | let a = (0..10).collect();\n | -------------------------- unnecessary let binding\n4 | a\n | ^\n |\n = note: `#[warn(clippy::let_and_return)]` on by default\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return\nhelp: return the expression directly\n |\n3 | \n4 | (0..10).collect()\n |\n\n",
|
||||
"children": [
|
||||
|
@ -1515,10 +1464,7 @@ mod tests {
|
|||
]
|
||||
}
|
||||
"##,
|
||||
expect_file!["crates/rust-analyzer/test_data/snap_multi_line_fix.txt"],
|
||||
);
|
||||
|
||||
let workspace_root = Path::new("/test/");
|
||||
let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root);
|
||||
insta::assert_debug_snapshot!(diag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ impl GlobalState {
|
|||
&workspace_root,
|
||||
);
|
||||
for diag in diagnostics {
|
||||
match url_to_file_id(&self.vfs.read().0, &diag.location.uri) {
|
||||
match url_to_file_id(&self.vfs.read().0, &diag.url) {
|
||||
Ok(file_id) => self.diagnostics.add_check_diagnostic(
|
||||
file_id,
|
||||
diag.diagnostic,
|
||||
|
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/compiler/mir/tagset.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 41,
|
||||
character: 23,
|
||||
},
|
||||
end: Position {
|
||||
line: 41,
|
||||
character: 28,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/compiler/mir/tagset.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/src/main.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 1,
|
||||
character: 4,
|
||||
},
|
||||
end: Position {
|
||||
line: 1,
|
||||
character: 26,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/src/main.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/crates/ra_hir_def/src/data.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 79,
|
||||
character: 15,
|
||||
},
|
||||
end: Position {
|
||||
line: 79,
|
||||
character: 41,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/crates/ra_hir_def/src/data.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/compiler/ty/list_iter.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 51,
|
||||
character: 4,
|
||||
},
|
||||
end: Position {
|
||||
line: 51,
|
||||
character: 47,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/compiler/ty/list_iter.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/runtime/compiler_support.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 47,
|
||||
character: 64,
|
||||
},
|
||||
end: Position {
|
||||
line: 47,
|
||||
character: 69,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/runtime/compiler_support.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/driver/subcommand/repl.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 290,
|
||||
character: 8,
|
||||
},
|
||||
end: Position {
|
||||
line: 290,
|
||||
character: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/driver/subcommand/repl.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/driver/subcommand/repl.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 290,
|
||||
character: 8,
|
||||
},
|
||||
end: Position {
|
||||
line: 290,
|
||||
character: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/driver/subcommand/repl.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/driver/subcommand/repl.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 290,
|
||||
character: 8,
|
||||
},
|
||||
end: Position {
|
||||
line: 290,
|
||||
character: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/driver/subcommand/repl.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/compiler/ty/select.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 103,
|
||||
character: 17,
|
||||
},
|
||||
end: Position {
|
||||
line: 103,
|
||||
character: 29,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/compiler/ty/select.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
|
@ -1,22 +1,6 @@
|
|||
---
|
||||
source: crates/rust-analyzer/src/diagnostics/to_proto.rs
|
||||
expression: diag
|
||||
---
|
||||
[
|
||||
MappedRustDiagnostic {
|
||||
location: Location {
|
||||
uri: "file:///test/src/main.rs",
|
||||
range: Range {
|
||||
start: Position {
|
||||
line: 3,
|
||||
character: 4,
|
||||
},
|
||||
end: Position {
|
||||
line: 3,
|
||||
character: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
url: "file:///test/src/main.rs",
|
||||
diagnostic: Diagnostic {
|
||||
range: Range {
|
||||
start: Position {
|
Loading…
Reference in a new issue