aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-10-24 17:29:38 +0100
committerAleksey Kladov <[email protected]>2019-10-24 17:29:38 +0100
commita40d02c9eb1c7226bc7db87b014dc827e77f2a08 (patch)
tree40108b506592ca6ae0fd4597f8b2cb7bdf414bfa
parenta409a12f1b3c7aa6c09405bf8e28f73b9761fd18 (diff)
refactor comment extraction from tasks
-rw-r--r--xtask/src/codegen.rs25
-rw-r--r--xtask/src/codegen/gen_parser_tests.rs58
2 files changed, 44 insertions, 39 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 e6eeb29a1..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
@@ -57,46 +57,28 @@ struct Tests {
57} 57}
58 58
59fn collect_tests(s: &str) -> Vec<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); 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 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[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<Test>, block: &[&str]) {
78 if block.is_empty() {
79 return;
80 }
81 let mut ok = true;
82 let mut block = block.iter();
83 let name = loop {
84 match block.next() {
85 Some(line) if line.starts_with("test ") => {
86 break line["test ".len()..].to_string();
87 }
88 Some(line) if line.starts_with("test_err ") => {
89 ok = false;
90 break line["test_err ".len()..].to_string();
91 }
92 Some(_) => (),
93 None => return,
94 }
95 }; 71 };
96 let text: String = block.copied().chain(std::iter::once("")).collect::<Vec<_>>().join("\n"); 72 let text: String = comment_block[1..]
73 .iter()
74 .cloned()
75 .chain(iter::once(String::new()))
76 .collect::<Vec<_>>()
77 .join("\n");
97 assert!(!text.trim().is_empty() && text.ends_with('\n')); 78 assert!(!text.trim().is_empty() && text.ends_with('\n'));
98 acc.push(Test { name, text, ok }) 79 res.push(Test { name, text, ok })
99 } 80 }
81 res
100} 82}
101 83
102fn tests_from_dir(dir: &Path) -> Result<Tests> { 84fn tests_from_dir(dir: &Path) -> Result<Tests> {