Repository: rust-analyzer/rust-analyzer
Pull request #5282 (2020-07-09 14:05:04)

Move diagnostics tests to expect


bors r+
🤖


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 84ca3344ce..b429aae01e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1435,9 +1435,9 @@ dependencies = [
  "anyhow",
  "crossbeam-channel",
  "env_logger",
+ "expect",
  "flycheck",
  "globset",
- "insta",
  "itertools",
  "jod-thread",
  "log",
diff --git a/crates/expect/src/lib.rs b/crates/expect/src/lib.rs
index c54e992038..21a458d477 100644
--- a/crates/expect/src/lib.rs
+++ b/crates/expect/src/lib.rs
@@ -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")
     }
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index 844b093d46..6804d9bda0 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -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)]
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index e4c57e41a0..48afee5fb4 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -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() },
         );
     }
 
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 62d364bfad..35ab741d82 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -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 {
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 837b6714d5..dc8dbbe772 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -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" }
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs
index b46281c985..d24c55cee6 100644
--- a/crates/rust-analyzer/src/diagnostics.rs
+++ b/crates/rust-analyzer/src/diagnostics.rs
@@ -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>,
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 3eed118a9b..b1b222deb8 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -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,
+    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
+            }
             Some(code) if config.warnings_as_info.contains(&code.code) => {
-                DiagnosticSeverity::Information
+                lsp_types::DiagnosticSeverity::Information
             }
-            _ => DiagnosticSeverity::Warning,
+            _ => 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);
     }
 }
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 5900886e7d..4e556bd506 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -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,


Test patch:
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index c2be236978..9191777455 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -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()
 }
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap b/crates/rust-analyzer/test_data/clippy_pass_by_ref.txt
similarity index 84%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap
rename to crates/rust-analyzer/test_data/clippy_pass_by_ref.txt
index d7f9ec0494..d065171260 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap
+++ b/crates/rust-analyzer/test_data/clippy_pass_by_ref.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap b/crates/rust-analyzer/test_data/handles_macro_location.txt
similarity index 64%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap
rename to crates/rust-analyzer/test_data/handles_macro_location.txt
index a59faf254c..f5de2f07f3 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap
+++ b/crates/rust-analyzer/test_data/handles_macro_location.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap b/crates/rust-analyzer/test_data/macro_compiler_error.txt
similarity index 75%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap
rename to crates/rust-analyzer/test_data/macro_compiler_error.txt
index 3c78e7f36c..f695db73ce 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap
+++ b/crates/rust-analyzer/test_data/macro_compiler_error.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap b/crates/rust-analyzer/test_data/rustc_incompatible_type_for_trait.txt
similarity index 67%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap
rename to crates/rust-analyzer/test_data/rustc_incompatible_type_for_trait.txt
index 46d0c56d22..fc54440be2 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap
+++ b/crates/rust-analyzer/test_data/rustc_incompatible_type_for_trait.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap b/crates/rust-analyzer/test_data/rustc_mismatched_type.txt
similarity index 62%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap
rename to crates/rust-analyzer/test_data/rustc_mismatched_type.txt
index 4182929ba3..c269af218c 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap
+++ b/crates/rust-analyzer/test_data/rustc_mismatched_type.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap b/crates/rust-analyzer/test_data/rustc_unused_variable.txt
similarity index 83%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap
rename to crates/rust-analyzer/test_data/rustc_unused_variable.txt
index 9a7972ff54..81f180a861 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap
+++ b/crates/rust-analyzer/test_data/rustc_unused_variable.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap b/crates/rust-analyzer/test_data/rustc_unused_variable_as_hint.txt
similarity index 83%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap
rename to crates/rust-analyzer/test_data/rustc_unused_variable_as_hint.txt
index f0273315e9..d5d78fd800 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap
+++ b/crates/rust-analyzer/test_data/rustc_unused_variable_as_hint.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap b/crates/rust-analyzer/test_data/rustc_unused_variable_as_info.txt
similarity index 83%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap
rename to crates/rust-analyzer/test_data/rustc_unused_variable_as_info.txt
index 85fd050fd7..2a7505c59f 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap
+++ b/crates/rust-analyzer/test_data/rustc_unused_variable_as_info.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap b/crates/rust-analyzer/test_data/rustc_wrong_number_of_parameters.txt
similarity index 77%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap
rename to crates/rust-analyzer/test_data/rustc_wrong_number_of_parameters.txt
index f6ab05004b..efe37261db 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap
+++ b/crates/rust-analyzer/test_data/rustc_wrong_number_of_parameters.txt
@@ -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 {
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap b/crates/rust-analyzer/test_data/snap_multi_line_fix.txt
similarity index 89%
rename from crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap
rename to crates/rust-analyzer/test_data/snap_multi_line_fix.txt
index 272057b47e..6eca3ae2f2 100644
--- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap
+++ b/crates/rust-analyzer/test_data/snap_multi_line_fix.txt
@@ -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 {