aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xtask/src/codegen.rs25
-rw-r--r--xtask/src/codegen/gen_parser_tests.rs63
2 files changed, 46 insertions, 42 deletions
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 948b86719..bf3a90119 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -8,7 +8,7 @@
8mod gen_syntax; 8mod gen_syntax;
9mod gen_parser_tests; 9mod gen_parser_tests;
10 10
11use std::{fs, path::Path}; 11use std::{fs, mem, path::Path};
12 12
13use crate::Result; 13use crate::Result;
14 14
@@ -44,3 +44,26 @@ pub fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
44 fs::write(path, contents)?; 44 fs::write(path, contents)?;
45 Ok(()) 45 Ok(())
46} 46}
47
48fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> {
49 let mut res = Vec::new();
50
51 let prefix = "// ";
52 let lines = text.lines().map(str::trim_start);
53
54 let mut block = vec![];
55 for line in lines {
56 let is_comment = line.starts_with(prefix);
57 if is_comment {
58 block.push(line[prefix.len()..].to_string());
59 } else {
60 if !block.is_empty() {
61 res.push(mem::replace(&mut block, Vec::new()))
62 }
63 }
64 }
65 if !block.is_empty() {
66 res.push(mem::replace(&mut block, Vec::new()))
67 }
68 res
69}
diff --git a/xtask/src/codegen/gen_parser_tests.rs b/xtask/src/codegen/gen_parser_tests.rs
index 0f550d948..db1e59dac 100644
--- a/xtask/src/codegen/gen_parser_tests.rs
+++ b/xtask/src/codegen/gen_parser_tests.rs
@@ -3,12 +3,12 @@
3 3
4use std::{ 4use std::{
5 collections::HashMap, 5 collections::HashMap,
6 fs, 6 fs, iter,
7 path::{Path, PathBuf}, 7 path::{Path, PathBuf},
8}; 8};
9 9
10use crate::{ 10use crate::{
11 codegen::{self, update, Mode}, 11 codegen::{self, extract_comment_blocks, update, Mode},
12 project_root, Result, 12 project_root, Result,
13}; 13};
14 14
@@ -56,48 +56,29 @@ struct Tests {
56 pub err: HashMap<String, Test>, 56 pub err: HashMap<String, Test>,
57} 57}
58 58
59fn collect_tests(s: &str) -> Vec<(usize, Test)> { 59fn collect_tests(s: &str) -> Vec<Test> {
60 let mut res = vec![]; 60 let mut res = Vec::new();
61 let prefix = "// "; 61 for comment_block in extract_comment_blocks(s) {
62 let lines = s.lines().map(str::trim_start).enumerate(); 62 let first_line = &comment_block[0];
63 63 let (name, ok) = if first_line.starts_with("test ") {
64 let mut block = vec![]; 64 let name = first_line["test ".len()..].to_string();
65 for (line_idx, line) in lines { 65 (name, true)
66 let is_comment = line.starts_with(prefix); 66 } else if first_line.starts_with("test_err ") {
67 if is_comment { 67 let name = first_line["test_err ".len()..].to_string();
68 block.push((line_idx, &line[prefix.len()..])); 68 (name, false)
69 } else { 69 } else {
70 process_block(&mut res, &block); 70 continue;
71 block.clear();
72 }
73 }
74 process_block(&mut res, &block);
75 return res;
76
77 fn process_block(acc: &mut Vec<(usize, Test)>, block: &[(usize, &str)]) {
78 if block.is_empty() {
79 return;
80 }
81 let mut ok = true;
82 let mut block = block.iter();
83 let (start_line, name) = loop {
84 match block.next() {
85 Some(&(idx, line)) if line.starts_with("test ") => {
86 break (idx, line["test ".len()..].to_string());
87 }
88 Some(&(idx, line)) if line.starts_with("test_err ") => {
89 ok = false;
90 break (idx, line["test_err ".len()..].to_string());
91 }
92 Some(_) => (),
93 None => return,
94 }
95 }; 71 };
96 let text: String = 72 let text: String = comment_block[1..]
97 block.map(|(_, line)| *line).chain(std::iter::once("")).collect::<Vec<_>>().join("\n"); 73 .iter()
74 .cloned()
75 .chain(iter::once(String::new()))
76 .collect::<Vec<_>>()
77 .join("\n");
98 assert!(!text.trim().is_empty() && text.ends_with('\n')); 78 assert!(!text.trim().is_empty() && text.ends_with('\n'));
99 acc.push((start_line, Test { name, text, ok })) 79 res.push(Test { name, text, ok })
100 } 80 }
81 res
101} 82}
102 83
103fn tests_from_dir(dir: &Path) -> Result<Tests> { 84fn tests_from_dir(dir: &Path) -> Result<Tests> {
@@ -118,7 +99,7 @@ fn tests_from_dir(dir: &Path) -> Result<Tests> {
118 fn process_file(res: &mut Tests, path: &Path) -> Result<()> { 99 fn process_file(res: &mut Tests, path: &Path) -> Result<()> {
119 let text = fs::read_to_string(path)?; 100 let text = fs::read_to_string(path)?;
120 101
121 for (_, test) in collect_tests(&text) { 102 for test in collect_tests(&text) {
122 if test.ok { 103 if test.ok {
123 if let Some(old_test) = res.ok.insert(test.name.clone(), test) { 104 if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
124 Err(format!("Duplicate test: {}", old_test.name))? 105 Err(format!("Duplicate test: {}", old_test.name))?