diff options
Diffstat (limited to 'crates/test_utils')
-rw-r--r-- | crates/test_utils/src/lib.rs | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 0a94adb74..beb936c61 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -10,22 +10,20 @@ pub const CURSOR_MARKER: &str = "<|>"; | |||
10 | 10 | ||
11 | #[macro_export] | 11 | #[macro_export] |
12 | macro_rules! assert_eq_text { | 12 | macro_rules! assert_eq_text { |
13 | ($expected:expr, $actual:expr) => {{ | 13 | ($expected:expr, $actual:expr) => { |
14 | let expected = $expected; | 14 | assert_eq_text!($expected, $actual,) |
15 | let actual = $actual; | 15 | }; |
16 | if expected != actual { | ||
17 | let changeset = $crate::__Changeset::new(actual, expected, "\n"); | ||
18 | println!("Expected:\n{}\n\nActual:\n{}\nDiff:{}\n", expected, actual, changeset); | ||
19 | panic!("text differs"); | ||
20 | } | ||
21 | }}; | ||
22 | ($expected:expr, $actual:expr, $($tt:tt)*) => {{ | 16 | ($expected:expr, $actual:expr, $($tt:tt)*) => {{ |
23 | let expected = $expected; | 17 | let expected = $expected; |
24 | let actual = $actual; | 18 | let actual = $actual; |
25 | if expected != actual { | 19 | if expected != actual { |
26 | let changeset = $crate::__Changeset::new(actual, expected, "\n"); | 20 | if expected.trim() == actual.trim() { |
27 | println!("Expected:\n{}\n\nActual:\n{}\n\nDiff:\n{}\n", expected, actual, changeset); | 21 | eprintln!("Expected:\n{:?}\n\nActual:\n{:?}\n\nWhitespace difference\n", expected, actual); |
28 | println!($($tt)*); | 22 | } else { |
23 | let changeset = $crate::__Changeset::new(actual, expected, "\n"); | ||
24 | eprintln!("Expected:\n{}\n\nActual:\n{}\n\nDiff:\n{}\n", expected, actual, changeset); | ||
25 | } | ||
26 | eprintln!($($tt)*); | ||
29 | panic!("text differs"); | 27 | panic!("text differs"); |
30 | } | 28 | } |
31 | }}; | 29 | }}; |
@@ -66,15 +64,40 @@ pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | |||
66 | Some((TextRange::from_to(start, end), text)) | 64 | Some((TextRange::from_to(start, end), text)) |
67 | } | 65 | } |
68 | 66 | ||
69 | pub fn extract_ranges(text: &str) -> (Vec<TextRange>, String) { | 67 | /// Extracts ranges, marked with `<tag> </tag>` paris from the `text` |
68 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | ||
69 | let open = format!("<{}>", tag); | ||
70 | let close = format!("</{}>", tag); | ||
70 | let mut ranges = Vec::new(); | 71 | let mut ranges = Vec::new(); |
71 | let mut text = String::from(text); | 72 | let mut res = String::new(); |
72 | while let Some((range, new_text)) = try_extract_range(&text) { | 73 | let mut stack = Vec::new(); |
73 | text = new_text; | 74 | loop { |
74 | ranges.push(range); | 75 | match text.find('<') { |
76 | None => { | ||
77 | res.push_str(text); | ||
78 | break; | ||
79 | } | ||
80 | Some(i) => { | ||
81 | res.push_str(&text[..i]); | ||
82 | text = &text[i..]; | ||
83 | if text.starts_with(&open) { | ||
84 | text = &text[open.len()..]; | ||
85 | let from = TextUnit::of_str(&res); | ||
86 | stack.push(from); | ||
87 | } else if text.starts_with(&close) { | ||
88 | text = &text[close.len()..]; | ||
89 | let from = stack | ||
90 | .pop() | ||
91 | .unwrap_or_else(|| panic!("unmatched </{}>", tag)); | ||
92 | let to = TextUnit::of_str(&res); | ||
93 | ranges.push(TextRange::from_to(from, to)); | ||
94 | } | ||
95 | } | ||
96 | } | ||
75 | } | 97 | } |
76 | 98 | assert!(stack.is_empty(), "unmatched <{}>", tag); | |
77 | (ranges, text) | 99 | ranges.sort_by_key(|r| (r.start(), r.end())); |
100 | (ranges, res) | ||
78 | } | 101 | } |
79 | 102 | ||
80 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { | 103 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { |