]> git.lizzy.rs Git - rust.git/blob - crates/tools/src/lib.rs
Merge #152
[rust.git] / crates / tools / src / lib.rs
1 extern crate itertools;
2 extern crate failure;
3 extern crate teraron;
4
5 use std::{
6     path::{Path, PathBuf},
7 };
8
9 use itertools::Itertools;
10
11 pub use teraron::{Mode, Verify, Overwrite};
12
13 pub type Result<T> = ::std::result::Result<T, failure::Error>;
14
15 pub const GRAMMAR: &str = "ra_syntax/src/grammar.ron";
16 pub const SYNTAX_KINDS: &str = "ra_syntax/src/syntax_kinds/generated.rs.tera";
17 pub const AST: &str = "ra_syntax/src/ast/generated.rs.tera";
18
19 #[derive(Debug)]
20 pub struct Test {
21     pub name: String,
22     pub text: String,
23 }
24
25 pub fn collect_tests(s: &str) -> Vec<(usize, Test)> {
26     let mut res = vec![];
27     let prefix = "// ";
28     let comment_blocks = s
29         .lines()
30         .map(str::trim_left)
31         .enumerate()
32         .group_by(|(_idx, line)| line.starts_with(prefix));
33
34     'outer: for (is_comment, block) in comment_blocks.into_iter() {
35         if !is_comment {
36             continue;
37         }
38         let mut block = block.map(|(idx, line)| (idx, &line[prefix.len()..]));
39
40         let (start_line, name) = loop {
41             match block.next() {
42                 Some((idx, line)) if line.starts_with("test ") => {
43                     break (idx, line["test ".len()..].to_string())
44                 }
45                 Some(_) => (),
46                 None => continue 'outer,
47             }
48         };
49         let text: String = itertools::join(
50             block.map(|(_, line)| line).chain(::std::iter::once("")),
51             "\n",
52         );
53         assert!(!text.trim().is_empty() && text.ends_with('\n'));
54         res.push((start_line, Test { name, text }))
55     }
56     res
57 }
58
59 pub fn generate(mode: Mode) -> Result<()> {
60     let grammar = project_root().join(GRAMMAR);
61     let syntax_kinds = project_root().join(SYNTAX_KINDS);
62     let ast = project_root().join(AST);
63     teraron::generate(
64         &syntax_kinds,
65         &grammar,
66         mode,
67     )?;
68     teraron::generate(
69         &ast,
70         &grammar,
71         mode,
72     )?;
73     Ok(())
74 }
75
76 pub fn project_root() -> PathBuf {
77     Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
78         .parent()
79         .unwrap()
80         .to_path_buf()
81 }