Skip to content

Commit eeb9823

Browse files
committed
parse fixture meta in test_utils crate
1 parent a4ecaa7 commit eeb9823

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

crates/test_utils/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ doctest = false
1111
difference = "2.0.0"
1212
text-size = "1.0.0"
1313
serde_json = "1.0.48"
14+
relative-path = "1.0.0"
15+
rustc-hash = "1.1.0"
16+
17+
ra_cfg = { path = "../ra_cfg" }

crates/test_utils/src/lib.rs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ use std::{
1414
path::{Path, PathBuf},
1515
};
1616

17+
pub use ra_cfg::CfgOptions;
18+
1719
use serde_json::Value;
1820
use text_size::{TextRange, TextSize};
21+
pub use relative_path::{RelativePath, RelativePathBuf};
22+
pub use rustc_hash::FxHashMap;
1923

2024
pub use difference::Changeset as __Changeset;
2125

@@ -159,6 +163,33 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
159163
pub struct FixtureEntry {
160164
pub meta: String,
161165
pub text: String,
166+
167+
pub parsed_meta: FixtureMeta,
168+
}
169+
170+
#[derive(Debug, Eq, PartialEq)]
171+
pub enum FixtureMeta {
172+
Root { path: RelativePathBuf },
173+
File(FileMeta),
174+
}
175+
176+
#[derive(Debug, Eq, PartialEq)]
177+
pub struct FileMeta {
178+
pub path: RelativePathBuf,
179+
pub krate: Option<String>,
180+
pub deps: Vec<String>,
181+
pub cfg: ra_cfg::CfgOptions,
182+
pub edition: Option<String>,
183+
pub env: FxHashMap<String, String>,
184+
}
185+
186+
impl FixtureMeta {
187+
pub fn path(&self) -> &RelativePath {
188+
match self {
189+
FixtureMeta::Root { path } => &path,
190+
FixtureMeta::File(f) => &f.path,
191+
}
192+
}
162193
}
163194

164195
/// Parses text which looks like this:
@@ -200,7 +231,8 @@ The offending line: {:?}"#,
200231
for line in lines.by_ref() {
201232
if line.starts_with("//-") {
202233
let meta = line["//-".len()..].trim().to_string();
203-
res.push(FixtureEntry { meta, text: String::new() })
234+
let parsed_meta = parse_meta(&meta);
235+
res.push(FixtureEntry { meta, parsed_meta, text: String::new() })
204236
} else if let Some(entry) = res.last_mut() {
205237
entry.text.push_str(line);
206238
entry.text.push('\n');
@@ -209,6 +241,58 @@ The offending line: {:?}"#,
209241
res
210242
}
211243

244+
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
245+
fn parse_meta(meta: &str) -> FixtureMeta {
246+
let components = meta.split_ascii_whitespace().collect::<Vec<_>>();
247+
248+
if components[0] == "root" {
249+
let path: RelativePathBuf = components[1].into();
250+
assert!(path.starts_with("/") && path.ends_with("/"));
251+
return FixtureMeta::Root { path };
252+
}
253+
254+
let path: RelativePathBuf = components[0].into();
255+
assert!(path.starts_with("/"));
256+
257+
let mut krate = None;
258+
let mut deps = Vec::new();
259+
let mut edition = None;
260+
let mut cfg = CfgOptions::default();
261+
let mut env = FxHashMap::default();
262+
for component in components[1..].iter() {
263+
let (key, value) = split1(component, ':').unwrap();
264+
match key {
265+
"crate" => krate = Some(value.to_string()),
266+
"deps" => deps = value.split(',').map(|it| it.to_string()).collect(),
267+
"edition" => edition = Some(value.to_string()),
268+
"cfg" => {
269+
for key in value.split(',') {
270+
match split1(key, '=') {
271+
None => cfg.insert_atom(key.into()),
272+
Some((k, v)) => cfg.insert_key_value(k.into(), v.into()),
273+
}
274+
}
275+
}
276+
"env" => {
277+
for key in value.split(',') {
278+
if let Some((k, v)) = split1(key, '=') {
279+
env.insert(k.into(), v.into());
280+
}
281+
}
282+
}
283+
_ => panic!("bad component: {:?}", component),
284+
}
285+
}
286+
287+
FixtureMeta::File(FileMeta { path, krate, deps, edition, cfg, env })
288+
}
289+
290+
fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> {
291+
let idx = haystack.find(delim)?;
292+
Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..]))
293+
}
294+
295+
212296
/// Adjusts the indentation of the first line to the minimum indentation of the rest of the lines.
213297
/// This allows fixtures to start off in a different indentation, e.g. to align the first line with
214298
/// the other lines visually:
@@ -288,6 +372,18 @@ struct Bar;
288372
)
289373
}
290374

375+
#[test]
376+
fn parse_fixture_gets_full_meta() {
377+
let fixture = r"
378+
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
379+
";
380+
let parsed = parse_fixture(fixture);
381+
assert_eq!(1, parsed.len());
382+
383+
let parsed = &parsed[0];
384+
assert_eq!("\n", parsed.text);
385+
}
386+
291387
/// Same as `parse_fixture`, except it allow empty fixture
292388
pub fn parse_single_fixture(fixture: &str) -> Option<FixtureEntry> {
293389
if !fixture.lines().any(|it| it.trim_start().starts_with("//-")) {

0 commit comments

Comments
 (0)