diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_syntax/tests/test.rs | 4 | ||||
-rw-r--r-- | crates/tools/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/tools/src/main.rs | 77 |
3 files changed, 56 insertions, 33 deletions
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs index 539c4435b..15f70c090 100644 --- a/crates/ra_syntax/tests/test.rs +++ b/crates/ra_syntax/tests/test.rs | |||
@@ -24,7 +24,7 @@ fn lexer_tests() { | |||
24 | 24 | ||
25 | #[test] | 25 | #[test] |
26 | fn parser_tests() { | 26 | fn parser_tests() { |
27 | dir_tests(&["parser/inline", "parser/ok"], |text, path| { | 27 | dir_tests(&["parser/inline/ok", "parser/ok"], |text, path| { |
28 | let file = SourceFileNode::parse(text); | 28 | let file = SourceFileNode::parse(text); |
29 | let errors = file.errors(); | 29 | let errors = file.errors(); |
30 | assert_eq!( | 30 | assert_eq!( |
@@ -35,7 +35,7 @@ fn parser_tests() { | |||
35 | ); | 35 | ); |
36 | dump_tree(file.syntax()) | 36 | dump_tree(file.syntax()) |
37 | }); | 37 | }); |
38 | dir_tests(&["parser/err"], |text, path| { | 38 | dir_tests(&["parser/err", "parser/inline/err"], |text, path| { |
39 | let file = SourceFileNode::parse(text); | 39 | let file = SourceFileNode::parse(text); |
40 | let errors = file.errors(); | 40 | let errors = file.errors(); |
41 | assert_ne!( | 41 | assert_ne!( |
diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 95d6e08f0..66fca5bef 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs | |||
@@ -21,6 +21,7 @@ const TOOLCHAIN: &str = "1.31.0"; | |||
21 | pub struct Test { | 21 | pub struct Test { |
22 | pub name: String, | 22 | pub name: String, |
23 | pub text: String, | 23 | pub text: String, |
24 | pub ok: bool, | ||
24 | } | 25 | } |
25 | 26 | ||
26 | pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { | 27 | pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { |
@@ -38,11 +39,16 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { | |||
38 | } | 39 | } |
39 | let mut block = block.map(|(idx, line)| (idx, &line[prefix.len()..])); | 40 | let mut block = block.map(|(idx, line)| (idx, &line[prefix.len()..])); |
40 | 41 | ||
42 | let mut ok = true; | ||
41 | let (start_line, name) = loop { | 43 | let (start_line, name) = loop { |
42 | match block.next() { | 44 | match block.next() { |
43 | Some((idx, line)) if line.starts_with("test ") => { | 45 | Some((idx, line)) if line.starts_with("test ") => { |
44 | break (idx, line["test ".len()..].to_string()); | 46 | break (idx, line["test ".len()..].to_string()); |
45 | } | 47 | } |
48 | Some((idx, line)) if line.starts_with("test_fail ") => { | ||
49 | ok = false; | ||
50 | break (idx, line["test_fail ".len()..].to_string()); | ||
51 | } | ||
46 | Some(_) => (), | 52 | Some(_) => (), |
47 | None => continue 'outer, | 53 | None => continue 'outer, |
48 | } | 54 | } |
@@ -52,7 +58,7 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { | |||
52 | "\n", | 58 | "\n", |
53 | ); | 59 | ); |
54 | assert!(!text.trim().is_empty() && text.ends_with('\n')); | 60 | assert!(!text.trim().is_empty() && text.ends_with('\n')); |
55 | res.push((start_line, Test { name, text })) | 61 | res.push((start_line, Test { name, text, ok })) |
56 | } | 62 | } |
57 | res | 63 | res |
58 | } | 64 | } |
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index 8e5e2036d..08b21f7af 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs | |||
@@ -7,10 +7,11 @@ use std::{ | |||
7 | use clap::{App, Arg, SubCommand}; | 7 | use clap::{App, Arg, SubCommand}; |
8 | use failure::bail; | 8 | use failure::bail; |
9 | 9 | ||
10 | use tools::{collect_tests, generate, install_format_hook, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify}; | 10 | use tools::{collect_tests, generate, install_format_hook, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify, project_root}; |
11 | 11 | ||
12 | const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; | 12 | const GRAMMAR_DIR: &str = "crates/ra_syntax/src/grammar"; |
13 | const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; | 13 | const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/ok"; |
14 | const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/err"; | ||
14 | 15 | ||
15 | fn main() -> Result<()> { | 16 | fn main() -> Result<()> { |
16 | let matches = App::new("tasks") | 17 | let matches = App::new("tasks") |
@@ -48,34 +49,43 @@ fn main() -> Result<()> { | |||
48 | 49 | ||
49 | fn gen_tests(mode: Mode) -> Result<()> { | 50 | fn gen_tests(mode: Mode) -> Result<()> { |
50 | let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?; | 51 | let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?; |
52 | fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> { | ||
53 | let tests_dir = project_root().join(into); | ||
54 | if !tests_dir.is_dir() { | ||
55 | fs::create_dir_all(&tests_dir)?; | ||
56 | } | ||
57 | // ok is never is actually read, but it needs to be specified to create a Test in existing_tests | ||
58 | let existing = existing_tests(&tests_dir, true)?; | ||
59 | for t in existing.keys().filter(|&t| !tests.contains_key(t)) { | ||
60 | panic!("Test is deleted: {}", t); | ||
61 | } | ||
51 | 62 | ||
52 | let inline_tests_dir = Path::new(INLINE_TESTS_DIR); | 63 | let mut new_idx = existing.len() + 2; |
53 | if !inline_tests_dir.is_dir() { | 64 | for (name, test) in tests { |
54 | fs::create_dir_all(inline_tests_dir)?; | 65 | let path = match existing.get(name) { |
55 | } | 66 | Some((path, _test)) => path.clone(), |
56 | let existing = existing_tests(inline_tests_dir)?; | 67 | None => { |
57 | 68 | let file_name = format!("{:04}_{}.rs", new_idx, name); | |
58 | for t in existing.keys().filter(|&t| !tests.contains_key(t)) { | 69 | new_idx += 1; |
59 | panic!("Test is deleted: {}", t); | 70 | tests_dir.join(file_name) |
71 | } | ||
72 | }; | ||
73 | teraron::update(&path, &test.text, mode)?; | ||
74 | } | ||
75 | Ok(()) | ||
60 | } | 76 | } |
77 | install_tests(&tests.ok, OK_INLINE_TESTS_DIR, mode)?; | ||
78 | install_tests(&tests.err, ERR_INLINE_TESTS_DIR, mode) | ||
79 | } | ||
61 | 80 | ||
62 | let mut new_idx = existing.len() + 2; | 81 | #[derive(Default, Debug)] |
63 | for (name, test) in tests { | 82 | struct Tests { |
64 | let path = match existing.get(&name) { | 83 | pub ok: HashMap<String, Test>, |
65 | Some((path, _test)) => path.clone(), | 84 | pub err: HashMap<String, Test>, |
66 | None => { | ||
67 | let file_name = format!("{:04}_{}.rs", new_idx, name); | ||
68 | new_idx += 1; | ||
69 | inline_tests_dir.join(file_name) | ||
70 | } | ||
71 | }; | ||
72 | teraron::update(&path, &test.text, mode)?; | ||
73 | } | ||
74 | Ok(()) | ||
75 | } | 85 | } |
76 | 86 | ||
77 | fn tests_from_dir(dir: &Path) -> Result<HashMap<String, Test>> { | 87 | fn tests_from_dir(dir: &Path) -> Result<Tests> { |
78 | let mut res = HashMap::new(); | 88 | let mut res = Tests::default(); |
79 | for entry in ::walkdir::WalkDir::new(dir) { | 89 | for entry in ::walkdir::WalkDir::new(dir) { |
80 | let entry = entry.unwrap(); | 90 | let entry = entry.unwrap(); |
81 | if !entry.file_type().is_file() { | 91 | if !entry.file_type().is_file() { |
@@ -89,19 +99,25 @@ fn tests_from_dir(dir: &Path) -> Result<HashMap<String, Test>> { | |||
89 | let grammar_rs = dir.parent().unwrap().join("grammar.rs"); | 99 | let grammar_rs = dir.parent().unwrap().join("grammar.rs"); |
90 | process_file(&mut res, &grammar_rs)?; | 100 | process_file(&mut res, &grammar_rs)?; |
91 | return Ok(res); | 101 | return Ok(res); |
92 | fn process_file(res: &mut HashMap<String, Test>, path: &Path) -> Result<()> { | 102 | fn process_file(res: &mut Tests, path: &Path) -> Result<()> { |
93 | let text = fs::read_to_string(path)?; | 103 | let text = fs::read_to_string(path)?; |
94 | 104 | ||
95 | for (_, test) in collect_tests(&text) { | 105 | for (_, test) in collect_tests(&text) { |
96 | if let Some(old_test) = res.insert(test.name.clone(), test) { | 106 | if test.ok { |
97 | bail!("Duplicate test: {}", old_test.name) | 107 | if let Some(old_test) = res.ok.insert(test.name.clone(), test) { |
108 | bail!("Duplicate test: {}", old_test.name) | ||
109 | } | ||
110 | } else { | ||
111 | if let Some(old_test) = res.err.insert(test.name.clone(), test) { | ||
112 | bail!("Duplicate test: {}", old_test.name) | ||
113 | } | ||
98 | } | 114 | } |
99 | } | 115 | } |
100 | Ok(()) | 116 | Ok(()) |
101 | } | 117 | } |
102 | } | 118 | } |
103 | 119 | ||
104 | fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> { | 120 | fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test)>> { |
105 | let mut res = HashMap::new(); | 121 | let mut res = HashMap::new(); |
106 | for file in fs::read_dir(dir)? { | 122 | for file in fs::read_dir(dir)? { |
107 | let file = file?; | 123 | let file = file?; |
@@ -117,6 +133,7 @@ fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> { | |||
117 | let test = Test { | 133 | let test = Test { |
118 | name: name.clone(), | 134 | name: name.clone(), |
119 | text, | 135 | text, |
136 | ok, | ||
120 | }; | 137 | }; |
121 | if let Some(old) = res.insert(name, (path, test)) { | 138 | if let Some(old) = res.insert(name, (path, test)) { |
122 | println!("Duplicate test: {:?}", old); | 139 | println!("Duplicate test: {:?}", old); |