aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils/src/fixture.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/test_utils/src/fixture.rs')
-rw-r--r--crates/test_utils/src/fixture.rs114
1 files changed, 19 insertions, 95 deletions
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs
index 0cd51ab3e..8747fa4a5 100644
--- a/crates/test_utils/src/fixture.rs
+++ b/crates/test_utils/src/fixture.rs
@@ -2,7 +2,7 @@
2//! rust-analyzer database from a single string. 2//! rust-analyzer database from a single string.
3 3
4use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5use stdx::split_delim; 5use stdx::{lines_with_ends, split_delim, trim_indent};
6 6
7#[derive(Debug, Eq, PartialEq)] 7#[derive(Debug, Eq, PartialEq)]
8pub struct Fixture { 8pub struct Fixture {
@@ -26,47 +26,35 @@ impl Fixture {
26 /// // - other meta 26 /// // - other meta
27 /// ``` 27 /// ```
28 pub fn parse(ra_fixture: &str) -> Vec<Fixture> { 28 pub fn parse(ra_fixture: &str) -> Vec<Fixture> {
29 let fixture = indent_first_line(ra_fixture); 29 let fixture = trim_indent(ra_fixture);
30 let margin = fixture_margin(&fixture);
31
32 let mut lines = fixture
33 .split('\n') // don't use `.lines` to not drop `\r\n`
34 .enumerate()
35 .filter_map(|(ix, line)| {
36 if line.len() >= margin {
37 assert!(line[..margin].trim().is_empty());
38 let line_content = &line[margin..];
39 if !line_content.starts_with("//-") {
40 assert!(
41 !line_content.contains("//-"),
42 r#"Metadata line {} has invalid indentation. All metadata lines need to have the same indentation.
43The offending line: {:?}"#,
44 ix,
45 line
46 );
47 }
48 Some(line_content)
49 } else {
50 assert!(line.trim().is_empty());
51 None
52 }
53 });
54 30
55 let mut res: Vec<Fixture> = Vec::new(); 31 let mut res: Vec<Fixture> = Vec::new();
56 for line in lines.by_ref() { 32
33 for (ix, line) in lines_with_ends(&fixture).enumerate() {
34 if line.contains("//-") {
35 assert!(
36 line.starts_with("//-"),
37 "Metadata line {} has invalid indentation. \
38 All metadata lines need to have the same indentation.\n\
39 The offending line: {:?}",
40 ix,
41 line
42 );
43 }
44
57 if line.starts_with("//-") { 45 if line.starts_with("//-") {
58 let meta = Fixture::parse_single(line); 46 let meta = Fixture::parse_meta_line(line);
59 res.push(meta) 47 res.push(meta)
60 } else if let Some(entry) = res.last_mut() { 48 } else if let Some(entry) = res.last_mut() {
61 entry.text.push_str(line); 49 entry.text.push_str(line);
62 entry.text.push('\n');
63 } 50 }
64 } 51 }
52
65 res 53 res
66 } 54 }
67 55
68 //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo 56 //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
69 pub fn parse_single(meta: &str) -> Fixture { 57 pub fn parse_meta_line(meta: &str) -> Fixture {
70 assert!(meta.starts_with("//-")); 58 assert!(meta.starts_with("//-"));
71 let meta = meta["//-".len()..].trim(); 59 let meta = meta["//-".len()..].trim();
72 let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); 60 let components = meta.split_ascii_whitespace().collect::<Vec<_>>();
@@ -118,51 +106,6 @@ The offending line: {:?}"#,
118 } 106 }
119} 107}
120 108
121/// Adjusts the indentation of the first line to the minimum indentation of the rest of the lines.
122/// This allows fixtures to start off in a different indentation, e.g. to align the first line with
123/// the other lines visually:
124/// ```
125/// let fixture = "//- /lib.rs
126/// mod foo;
127/// //- /foo.rs
128/// fn bar() {}
129/// ";
130/// assert_eq!(fixture_margin(fixture),
131/// " //- /lib.rs
132/// mod foo;
133/// //- /foo.rs
134/// fn bar() {}
135/// ")
136/// ```
137fn indent_first_line(fixture: &str) -> String {
138 if fixture.is_empty() {
139 return String::new();
140 }
141 let mut lines = fixture.lines();
142 let first_line = lines.next().unwrap();
143 if first_line.contains("//-") {
144 let rest = lines.collect::<Vec<_>>().join("\n");
145 let fixed_margin = fixture_margin(&rest);
146 let fixed_indent = fixed_margin - indent_len(first_line);
147 format!("\n{}{}\n{}", " ".repeat(fixed_indent), first_line, rest)
148 } else {
149 fixture.to_owned()
150 }
151}
152
153fn fixture_margin(fixture: &str) -> usize {
154 fixture
155 .lines()
156 .filter(|it| it.trim_start().starts_with("//-"))
157 .map(indent_len)
158 .next()
159 .expect("empty fixture")
160}
161
162fn indent_len(s: &str) -> usize {
163 s.len() - s.trim_start().len()
164}
165
166#[test] 109#[test]
167#[should_panic] 110#[should_panic]
168fn parse_fixture_checks_further_indented_metadata() { 111fn parse_fixture_checks_further_indented_metadata() {
@@ -179,25 +122,6 @@ fn parse_fixture_checks_further_indented_metadata() {
179} 122}
180 123
181#[test] 124#[test]
182fn parse_fixture_can_handle_dedented_first_line() {
183 let fixture = "//- /lib.rs
184 mod foo;
185 //- /foo.rs
186 struct Bar;
187";
188 assert_eq!(
189 Fixture::parse(fixture),
190 Fixture::parse(
191 "//- /lib.rs
192mod foo;
193//- /foo.rs
194struct Bar;
195"
196 )
197 )
198}
199
200#[test]
201fn parse_fixture_gets_full_meta() { 125fn parse_fixture_gets_full_meta() {
202 let parsed = Fixture::parse( 126 let parsed = Fixture::parse(
203 r" 127 r"
@@ -208,7 +132,7 @@ fn parse_fixture_gets_full_meta() {
208 assert_eq!(1, parsed.len()); 132 assert_eq!(1, parsed.len());
209 133
210 let meta = &parsed[0]; 134 let meta = &parsed[0];
211 assert_eq!("mod m;\n\n", meta.text); 135 assert_eq!("mod m;\n", meta.text);
212 136
213 assert_eq!("foo", meta.crate_name.as_ref().unwrap()); 137 assert_eq!("foo", meta.crate_name.as_ref().unwrap());
214 assert_eq!("/lib.rs", meta.path); 138 assert_eq!("/lib.rs", meta.path);