about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/expect/src/lib.rs97
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs22
-rw-r--r--crates/ra_ide/test_data/highlight_doctest.html (renamed from crates/ra_ide/src/snapshots/highlight_doctest.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_injection.html (renamed from crates/ra_ide/src/snapshots/highlight_injection.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_strings.html (renamed from crates/ra_ide/src/snapshots/highlight_strings.html)0
-rw-r--r--crates/ra_ide/test_data/highlight_unsafe.html (renamed from crates/ra_ide/src/snapshots/highlight_unsafe.html)0
-rw-r--r--crates/ra_ide/test_data/highlighting.html (renamed from crates/ra_ide/src/snapshots/highlighting.html)0
-rw-r--r--crates/ra_ide/test_data/rainbow_highlighting.html (renamed from crates/ra_ide/src/snapshots/rainbow_highlighting.html)0
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
9 files changed, 87 insertions, 34 deletions
diff --git a/crates/expect/src/lib.rs b/crates/expect/src/lib.rs
index dd7b96aab26..a5e26faded7 100644
--- a/crates/expect/src/lib.rs
+++ b/crates/expect/src/lib.rs
@@ -2,7 +2,7 @@
 //! https://github.com/rust-analyzer/rust-analyzer/pull/5101
 use std::{
     collections::HashMap,
-    env, fmt, fs,
+    env, fmt, fs, mem,
     ops::Range,
     panic,
     path::{Path, PathBuf},
@@ -14,7 +14,7 @@ use once_cell::sync::Lazy;
 use stdx::{lines_with_ends, trim_indent};
 
 const HELP: &str = "
-You can update all `expect![[]]` tests by:
+You can update all `expect![[]]` tests by running:
 
     env UPDATE_EXPECT=1 cargo test
 
@@ -25,24 +25,48 @@ fn update_expect() -> bool {
     env::var("UPDATE_EXPECT").is_ok()
 }
 
-/// expect![[""]]
+/// expect![[r#"inline snapshot"#]]
 #[macro_export]
 macro_rules! expect {
-    [[$lit:literal]] => {$crate::Expect {
-        file: file!(),
-        line: line!(),
-        column: column!(),
-        data: $lit,
+    [[$data:literal]] => {$crate::Expect {
+        position: $crate::Position {
+            file: file!(),
+            line: line!(),
+            column: column!(),
+        },
+        data: $data,
     }};
     [[]] => { $crate::expect![[""]] };
 }
 
+/// expect_file!["/crates/foo/test_data/bar.html"]
+#[macro_export]
+macro_rules! expect_file {
+    [$path:literal] => {$crate::ExpectFile { path: $path }};
+}
+
 #[derive(Debug)]
 pub struct Expect {
+    pub position: Position,
+    pub data: &'static str,
+}
+
+#[derive(Debug)]
+pub struct ExpectFile {
+    pub path: &'static str,
+}
+
+#[derive(Debug)]
+pub struct Position {
     pub file: &'static str,
     pub line: u32,
     pub column: u32,
-    pub data: &'static str,
+}
+
+impl fmt::Display for Position {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}:{}:{}", self.file, self.line, self.column)
+    }
 }
 
 impl Expect {
@@ -51,7 +75,7 @@ impl Expect {
         if &trimmed == actual {
             return;
         }
-        Runtime::fail(self, &trimmed, actual);
+        Runtime::fail_expect(self, &trimmed, actual);
     }
     pub fn assert_debug_eq(&self, actual: &impl fmt::Debug) {
         let actual = format!("{:#?}\n", actual);
@@ -69,7 +93,7 @@ impl Expect {
         let mut target_line = None;
         let mut line_start = 0;
         for (i, line) in lines_with_ends(file).enumerate() {
-            if i == self.line as usize - 1 {
+            if i == self.position.line as usize - 1 {
                 let pat = "expect![[";
                 let offset = line.find(pat).unwrap();
                 let literal_start = line_start + offset + pat.len();
@@ -87,6 +111,25 @@ impl Expect {
     }
 }
 
+impl ExpectFile {
+    pub fn assert_eq(&self, actual: &str) {
+        let expected = self.read();
+        if actual == expected {
+            return;
+        }
+        Runtime::fail_file(self, &expected, actual);
+    }
+    fn read(&self) -> String {
+        fs::read_to_string(self.abs_path()).unwrap_or_default().replace("\r\n", "\n")
+    }
+    fn write(&self, contents: &str) {
+        fs::write(self.abs_path(), contents).unwrap()
+    }
+    fn abs_path(&self) -> PathBuf {
+        workspace_root().join(self.path)
+    }
+}
+
 #[derive(Default)]
 struct Runtime {
     help_printed: bool,
@@ -95,27 +138,39 @@ struct Runtime {
 static RT: Lazy<Mutex<Runtime>> = Lazy::new(Default::default);
 
 impl Runtime {
-    fn fail(expect: &Expect, expected: &str, actual: &str) {
+    fn fail_expect(expect: &Expect, expected: &str, actual: &str) {
         let mut rt = RT.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
-        let mut updated = "";
         if update_expect() {
-            updated = " (updated)";
+            println!("\x1b[1m\x1b[92mupdating\x1b[0m: {}", expect.position);
             rt.per_file
-                .entry(expect.file)
+                .entry(expect.position.file)
                 .or_insert_with(|| FileRuntime::new(expect))
                 .update(expect, actual);
+            return;
         }
-        let print_help = !rt.help_printed && !update_expect();
-        rt.help_printed = true;
+        rt.panic(expect.position.to_string(), expected, actual);
+    }
+
+    fn fail_file(expect: &ExpectFile, expected: &str, actual: &str) {
+        let mut rt = RT.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
+        if update_expect() {
+            println!("\x1b[1m\x1b[92mupdating\x1b[0m: {}", expect.path);
+            expect.write(actual);
+            return;
+        }
+        rt.panic(expect.path.to_string(), expected, actual);
+    }
 
+    fn panic(&mut self, position: String, expected: &str, actual: &str) {
+        let print_help = !mem::replace(&mut self.help_printed, true);
         let help = if print_help { HELP } else { "" };
 
         let diff = Changeset::new(actual, expected, "\n");
 
         println!(
             "\n
-\x1b[1m\x1b[91merror\x1b[97m: expect test failed\x1b[0m{}
-   \x1b[1m\x1b[34m-->\x1b[0m {}:{}:{}
+\x1b[1m\x1b[91merror\x1b[97m: expect test failed\x1b[0m
+   \x1b[1m\x1b[34m-->\x1b[0m {}
 {}
 \x1b[1mExpect\x1b[0m:
 ----
@@ -132,7 +187,7 @@ impl Runtime {
 {}
 ----
 ",
-            updated, expect.file, expect.line, expect.column, help, expected, actual, diff
+            position, help, expected, actual, diff
         );
         // Use resume_unwind instead of panic!() to prevent a backtrace, which is unnecessary noise.
         panic::resume_unwind(Box::new(()));
@@ -147,7 +202,7 @@ struct FileRuntime {
 
 impl FileRuntime {
     fn new(expect: &Expect) -> FileRuntime {
-        let path = workspace_root().join(expect.file);
+        let path = workspace_root().join(expect.position.file);
         let original_text = fs::read_to_string(&path).unwrap();
         let patchwork = Patchwork::new(original_text.clone());
         FileRuntime { path, original_text, patchwork }
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index b7fad97197f..aa7c887d674 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -1,6 +1,7 @@
 use std::fs;
 
-use test_utils::{assert_eq_text, project_dir, read_text};
+use expect::{expect_file, ExpectFile};
+use test_utils::project_dir;
 
 use crate::{mock_analysis::single_file, FileRange, TextRange};
 
@@ -91,7 +92,7 @@ impl<T> Option<T> {
 }
 "#
         .trim(),
-        "crates/ra_ide/src/snapshots/highlighting.html",
+        expect_file!["crates/ra_ide/test_data/highlighting.html"],
         false,
     );
 }
@@ -114,7 +115,7 @@ fn bar() {
 }
 "#
         .trim(),
-        "crates/ra_ide/src/snapshots/rainbow_highlighting.html",
+        expect_file!["crates/ra_ide/test_data/rainbow_highlighting.html"],
         true,
     );
 }
@@ -167,7 +168,7 @@ fn main() {
     );
 }"##
         .trim(),
-        "crates/ra_ide/src/snapshots/highlight_injection.html",
+        expect_file!["crates/ra_ide/test_data/highlight_injection.html"],
         false,
     );
 }
@@ -250,7 +251,7 @@ fn main() {
     println!("{ничоси}", ничоси = 92);
 }"#
         .trim(),
-        "crates/ra_ide/src/snapshots/highlight_strings.html",
+        expect_file!["crates/ra_ide/test_data/highlight_strings.html"],
         false,
     );
 }
@@ -278,7 +279,7 @@ fn main() {
 }
 "#
         .trim(),
-        "crates/ra_ide/src/snapshots/highlight_unsafe.html",
+        expect_file!["crates/ra_ide/test_data/highlight_unsafe.html"],
         false,
     );
 }
@@ -354,7 +355,7 @@ macro_rules! noop {
 }
 "#
         .trim(),
-        "crates/ra_ide/src/snapshots/highlight_doctest.html",
+        expect_file!["crates/ra_ide/test_data/highlight_doctest.html"],
         false,
     );
 }
@@ -362,11 +363,8 @@ macro_rules! noop {
 /// Highlights the code given by the `ra_fixture` argument, renders the
 /// result as HTML, and compares it with the HTML file given as `snapshot`.
 /// Note that the `snapshot` file is overwritten by the rendered HTML.
-fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) {
+fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) {
     let (analysis, file_id) = single_file(ra_fixture);
-    let dst_file = project_dir().join(snapshot);
     let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
-    let expected_html = &read_text(&dst_file);
-    fs::write(dst_file, &actual_html).unwrap();
-    assert_eq_text!(expected_html, actual_html);
+    expect.assert_eq(actual_html)
 }
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/test_data/highlight_doctest.html
index e8155def75e..e8155def75e 100644
--- a/crates/ra_ide/src/snapshots/highlight_doctest.html
+++ b/crates/ra_ide/test_data/highlight_doctest.html
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/test_data/highlight_injection.html
index 1b0349bae2e..1b0349bae2e 100644
--- a/crates/ra_ide/src/snapshots/highlight_injection.html
+++ b/crates/ra_ide/test_data/highlight_injection.html
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/test_data/highlight_strings.html
index d184b569102..d184b569102 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/test_data/highlight_strings.html
diff --git a/crates/ra_ide/src/snapshots/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index 6936e949fe8..6936e949fe8 100644
--- a/crates/ra_ide/src/snapshots/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/test_data/highlighting.html
index 8d0b38f958d..8d0b38f958d 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/test_data/highlighting.html
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/test_data/rainbow_highlighting.html
index 9516c744104..9516c744104 100644
--- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide/test_data/rainbow_highlighting.html
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 25bcd80af8c..607a95682a7 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -415,7 +415,7 @@ pub(crate) fn handle_runnables(
             let source_file = snap.analysis.parse(file_id)?;
             algo::find_node_at_offset::<ast::MacroCall>(source_file.syntax(), offset)
                 .and_then(|it| it.path()?.segment()?.name_ref())
-                .map_or(false, |it| it.text() == "expect")
+                .map_or(false, |it| it.text() == "expect" || it.text() == "expect_file")
         }
         None => false,
     };