From 23449e46f2ed4e1ca7b5179896792662915d2cdb Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 26 Dec 2021 13:35:51 -0800 Subject: [PATCH 1/6] Support single delimiters in `expect!` Now that we parse string literals, multiple delimiters aren't necessary. --- src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0dbbb76..5d130ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -175,6 +175,7 @@ fn update_expect() -> bool { /// Leading indentation is stripped. #[macro_export] macro_rules! expect { + [$data:literal] => { $crate::expect![[$data]] }; [[$data:literal]] => {$crate::Expect { position: $crate::Position { file: file!(), @@ -184,6 +185,7 @@ macro_rules! expect { data: $data, indent: true, }}; + [] => { $crate::expect![[""]] }; [[]] => { $crate::expect![[""]] }; } @@ -336,7 +338,7 @@ impl Expect { let literal_start = literal_start + (lit_to_eof.len() - lit_to_eof_trimmed.len()); let literal_len = - locate_end(lit_to_eof_trimmed).expect("Couldn't find matching `]]` for `expect![[`."); + locate_end(lit_to_eof_trimmed).expect("Couldn't find closing delimiter for `expect!`."); let literal_range = literal_start..literal_start + literal_len; Location { line_indent, literal_range } } @@ -345,7 +347,8 @@ impl Expect { fn locate_end(lit_to_eof: &str) -> Option { assert!(lit_to_eof.chars().next().map_or(true, |c| !c.is_whitespace())); - if lit_to_eof.starts_with("]]") { + let first = lit_to_eof.chars().next()?; + if matches!(first, ']' | '}' | ')') { // expect![[ ]] Some(0) } else { From a297f72c57d6125d39561ab73cf0297e1e0fc6fe Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 26 Dec 2021 14:03:00 -0800 Subject: [PATCH 2/6] Update documentation/messages to reflect single-delimiter support --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5d130ad..ad3cc9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ //! use expect_test::expect; //! //! let actual = 2 + 2; -//! let expected = expect![["5"]]; +//! let expected = expect!["5"]; // or expect![["5"]] //! expected.assert_eq(&actual.to_string()) //! ``` //! @@ -25,7 +25,7 @@ //! ```no_run //! # use expect_test::expect; //! let actual = 2 + 2; -//! let expected = expect![["4"]]; +//! let expected = expect!["4"]; //! expected.assert_eq(&actual.to_string()) //! ``` //! @@ -152,7 +152,7 @@ use std::{ use once_cell::sync::{Lazy, OnceCell}; const HELP: &str = " -You can update all `expect![[]]` tests by running: +You can update all `expect!` tests by running: env UPDATE_EXPECT=1 cargo test @@ -170,6 +170,7 @@ fn update_expect() -> bool { /// expect![[" /// Foo { value: 92 } /// "]]; +/// expect![r#"{"Foo": 92}"#]; /// ``` /// /// Leading indentation is stripped. From 93d150e71136d8632d1269e191d31c069447ef77 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Jan 2022 12:19:25 -0800 Subject: [PATCH 3/6] Include inner braces as part of the literal range --- src/lib.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ad3cc9a..a87673b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -308,18 +308,20 @@ impl Expect { if i == self.position.line as usize - 1 { // `column` points to the first character of the macro invocation: // - // expect![[ ... ]] - // ^ + // expect![[r#""#]] expect![""] + // ^ ^ ^ ^ + // column offset offset // // Seek past the exclam, then skip any whitespace and - // delimiters to get to our argument. + // the macro delimiter to get to our argument. let byte_offset = line .char_indices() .skip((self.position.column - 1).try_into().unwrap()) .skip_while(|&(_, c)| c != '!') - .skip(1) + .skip(1) // ! + .skip_while(|&(_, c)| c.is_whitespace()) + .skip(1) // [({ .skip_while(|&(_, c)| c.is_whitespace()) - .skip_while(|&(_, c)| matches!(c, '[' | '(' | '{')) .next() .expect("Failed to parse macro invocation") .0; @@ -345,16 +347,24 @@ impl Expect { } } -fn locate_end(lit_to_eof: &str) -> Option { - assert!(lit_to_eof.chars().next().map_or(true, |c| !c.is_whitespace())); +fn locate_end(arg_start_to_eof: &str) -> Option { + match arg_start_to_eof.chars().next()? { + c if c.is_whitespace() => panic!("skip whitespace before calling `locate_end`"), + + // expect![[]] + '[' => { + let str_start_to_eof = arg_start_to_eof[1..].trim_start(); + let str_len = find_str_lit_len(str_start_to_eof)?; + let str_end_to_eof = &str_start_to_eof[str_len..]; + let closing_brace_offset = str_end_to_eof.find(']')?; + Some((arg_start_to_eof.len() - str_end_to_eof.len()) + closing_brace_offset + 1) + } + + // expect![] | expect!{} | expect!() + ']' | '}' | ')' => Some(0), - let first = lit_to_eof.chars().next()?; - if matches!(first, ']' | '}' | ')') { - // expect![[ ]] - Some(0) - } else { - // expect![["foo"]] - find_str_lit_len(lit_to_eof) + // expect!["..."] | expect![r#"..."#] + _ => find_str_lit_len(arg_start_to_eof), } } @@ -537,6 +547,8 @@ impl FileRuntime { #[derive(Debug)] struct Location { line_indent: usize, + + /// The byte range of the argument to `expect!`, including the inner `[]` if it exists. literal_range: Range, } From 8e2507d5b0f9e873e9fa54de0d7f57eddf724a04 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Jan 2022 12:24:32 -0800 Subject: [PATCH 4/6] Add inner delimiters to patch when using a raw string --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index a87673b..c1d996f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -606,6 +606,9 @@ fn format_patch(desired_indent: Option, patch: &str) -> String { let is_multiline = patch.contains('\n'); let mut buf = String::new(); + if matches!(lit_kind, StrLitKind::Raw(_)) { + buf.push('['); + } lit_kind.write_start(&mut buf).unwrap(); if is_multiline { buf.push('\n'); @@ -627,6 +630,9 @@ fn format_patch(desired_indent: Option, patch: &str) -> String { } } lit_kind.write_end(&mut buf).unwrap(); + if matches!(lit_kind, StrLitKind::Raw(_)) { + buf.push(']'); + } buf } From f09be07b44535323cd26c8431f95ca4091c5c166 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Jan 2022 12:25:04 -0800 Subject: [PATCH 5/6] Update `format_patch` tests to include the inner braces --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c1d996f..505ba60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -728,24 +728,24 @@ mod tests { fn test_format_patch() { let patch = format_patch(None, "hello\nworld\n"); expect![[r##" - r#" + [r#" hello world - "#"##]] + "#]"##]] .assert_eq(&patch); let patch = format_patch(None, r"hello\tworld"); - expect![[r##"r#"hello\tworld"#"##]].assert_eq(&patch); + expect![[r##"[r#"hello\tworld"#]"##]].assert_eq(&patch); let patch = format_patch(None, "{\"foo\": 42}"); - expect![[r##"r#"{"foo": 42}"#"##]].assert_eq(&patch); + expect![[r##"[r#"{"foo": 42}"#]"##]].assert_eq(&patch); let patch = format_patch(Some(0), "hello\nworld\n"); expect![[r##" - r#" + [r#" hello world - "#"##]] + "#]"##]] .assert_eq(&patch); let patch = format_patch(Some(4), "single line"); From d7c381ef7039e5b62143ba1f5fe1b3ac480cb27a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Jan 2022 12:25:24 -0800 Subject: [PATCH 6/6] Add a simple `expect` invocation to the test suite I'm modifying this to check that `UPDATE_EXPECT` works manually. --- src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 505ba60..1e93a3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -724,6 +724,11 @@ fn format_chunks(chunks: Vec) -> String { mod tests { use super::*; + #[test] + fn test_trivial_assert() { + expect!["5"].assert_eq("5"); + } + #[test] fn test_format_patch() { let patch = format_patch(None, "hello\nworld\n");