diff options
Diffstat (limited to 'crates/tools')
-rw-r--r-- | crates/tools/Cargo.toml | 4 | ||||
-rw-r--r-- | crates/tools/src/lib.rs | 85 | ||||
-rw-r--r-- | crates/tools/src/main.rs | 36 | ||||
-rw-r--r-- | crates/tools/tests/cli.rs | 15 |
4 files changed, 36 insertions, 104 deletions
diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index e2fecc60d..41b19c5c6 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml | |||
@@ -6,10 +6,8 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
6 | publish = false | 6 | publish = false |
7 | 7 | ||
8 | [dependencies] | 8 | [dependencies] |
9 | ron = "0.3.0" | 9 | teraron = "0.0.1" |
10 | walkdir = "2.1.3" | 10 | walkdir = "2.1.3" |
11 | itertools = "0.7.8" | 11 | itertools = "0.7.8" |
12 | tera = "0.11" | ||
13 | clap = "2.32.0" | 12 | clap = "2.32.0" |
14 | failure = "0.1.1" | 13 | failure = "0.1.1" |
15 | heck = "0.3.0" | ||
diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 5d5d372bb..444745be5 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs | |||
@@ -1,25 +1,20 @@ | |||
1 | extern crate itertools; | 1 | extern crate itertools; |
2 | #[macro_use] | ||
3 | extern crate failure; | 2 | extern crate failure; |
4 | extern crate heck; | 3 | extern crate teraron; |
5 | extern crate ron; | ||
6 | extern crate tera; | ||
7 | 4 | ||
8 | use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; | ||
9 | use itertools::Itertools; | ||
10 | use std::{ | 5 | use std::{ |
11 | collections::HashMap, | ||
12 | fs, | ||
13 | path::{Path, PathBuf}, | 6 | path::{Path, PathBuf}, |
14 | }; | 7 | }; |
15 | 8 | ||
9 | use itertools::Itertools; | ||
10 | |||
11 | pub use teraron::{Mode, Verify, Overwrite}; | ||
12 | |||
16 | pub type Result<T> = ::std::result::Result<T, failure::Error>; | 13 | pub type Result<T> = ::std::result::Result<T, failure::Error>; |
17 | 14 | ||
18 | const GRAMMAR: &str = "ra_syntax/src/grammar.ron"; | 15 | pub const GRAMMAR: &str = "ra_syntax/src/grammar.ron"; |
19 | pub const SYNTAX_KINDS: &str = "ra_syntax/src/syntax_kinds/generated.rs"; | 16 | pub const SYNTAX_KINDS: &str = "ra_syntax/src/syntax_kinds/generated.rs.tera"; |
20 | pub const SYNTAX_KINDS_TEMPLATE: &str = "ra_syntax/src/syntax_kinds/generated.rs.tera"; | 17 | pub const AST: &str = "ra_syntax/src/ast/generated.rs.tera"; |
21 | pub const AST: &str = "ra_syntax/src/ast/generated.rs"; | ||
22 | pub const AST_TEMPLATE: &str = "ra_syntax/src/ast/generated.rs.tera"; | ||
23 | 18 | ||
24 | #[derive(Debug)] | 19 | #[derive(Debug)] |
25 | pub struct Test { | 20 | pub struct Test { |
@@ -61,59 +56,23 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { | |||
61 | res | 56 | res |
62 | } | 57 | } |
63 | 58 | ||
64 | pub fn update(path: &Path, contents: &str, verify: bool) -> Result<()> { | 59 | pub fn generate(mode: Mode) -> Result<()> { |
65 | match fs::read_to_string(path) { | 60 | let grammar = project_root().join(GRAMMAR); |
66 | Ok(ref old_contents) if old_contents == contents => { | 61 | let syntax_kinds = project_root().join(SYNTAX_KINDS); |
67 | return Ok(()); | 62 | let ast = project_root().join(AST); |
68 | } | 63 | teraron::generate( |
69 | _ => (), | 64 | &syntax_kinds, |
70 | } | 65 | &grammar, |
71 | if verify { | 66 | mode, |
72 | bail!("`{}` is not up-to-date", path.display()); | 67 | )?; |
73 | } | 68 | teraron::generate( |
74 | eprintln!("updating {}", path.display()); | 69 | &ast, |
75 | fs::write(path, contents)?; | 70 | &grammar, |
71 | mode, | ||
72 | )?; | ||
76 | Ok(()) | 73 | Ok(()) |
77 | } | 74 | } |
78 | 75 | ||
79 | pub fn render_template(template: &Path) -> Result<String> { | ||
80 | let grammar: ron::value::Value = { | ||
81 | let text = fs::read_to_string(project_root().join(GRAMMAR))?; | ||
82 | ron::de::from_str(&text)? | ||
83 | }; | ||
84 | let template = fs::read_to_string(template)?; | ||
85 | let mut tera = tera::Tera::default(); | ||
86 | tera.add_raw_template("grammar", &template) | ||
87 | .map_err(|e| format_err!("template error: {:?}", e))?; | ||
88 | tera.register_function("concat", Box::new(concat)); | ||
89 | tera.register_filter("camel", |arg, _| { | ||
90 | Ok(arg.as_str().unwrap().to_camel_case().into()) | ||
91 | }); | ||
92 | tera.register_filter("snake", |arg, _| { | ||
93 | Ok(arg.as_str().unwrap().to_snake_case().into()) | ||
94 | }); | ||
95 | tera.register_filter("SCREAM", |arg, _| { | ||
96 | Ok(arg.as_str().unwrap().to_shouty_snake_case().into()) | ||
97 | }); | ||
98 | let ret = tera | ||
99 | .render("grammar", &grammar) | ||
100 | .map_err(|e| format_err!("template error: {:?}", e))?; | ||
101 | return Ok(ret); | ||
102 | |||
103 | fn concat(args: HashMap<String, tera::Value>) -> tera::Result<tera::Value> { | ||
104 | let mut elements = Vec::new(); | ||
105 | for &key in ["a", "b", "c"].iter() { | ||
106 | let val = match args.get(key) { | ||
107 | Some(val) => val, | ||
108 | None => continue, | ||
109 | }; | ||
110 | let val = val.as_array().unwrap(); | ||
111 | elements.extend(val.iter().cloned()); | ||
112 | } | ||
113 | Ok(tera::Value::Array(elements)) | ||
114 | } | ||
115 | } | ||
116 | |||
117 | pub fn project_root() -> PathBuf { | 76 | pub fn project_root() -> PathBuf { |
118 | Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) | 77 | Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) |
119 | .parent() | 78 | .parent() |
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index b662d78df..965bc7729 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs | |||
@@ -3,6 +3,7 @@ extern crate clap; | |||
3 | extern crate failure; | 3 | extern crate failure; |
4 | extern crate tools; | 4 | extern crate tools; |
5 | extern crate walkdir; | 5 | extern crate walkdir; |
6 | extern crate teraron; | ||
6 | 7 | ||
7 | use clap::{App, Arg, SubCommand}; | 8 | use clap::{App, Arg, SubCommand}; |
8 | use std::{ | 9 | use std::{ |
@@ -12,8 +13,7 @@ use std::{ | |||
12 | process::Command, | 13 | process::Command, |
13 | }; | 14 | }; |
14 | use tools::{ | 15 | use tools::{ |
15 | collect_tests, project_root, render_template, update, Result, Test, AST, AST_TEMPLATE, | 16 | collect_tests, Result, Test, generate, Mode, Overwrite, Verify, |
16 | SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, | ||
17 | }; | 17 | }; |
18 | 18 | ||
19 | const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; | 19 | const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; |
@@ -32,35 +32,21 @@ fn main() -> Result<()> { | |||
32 | .subcommand(SubCommand::with_name("gen-tests")) | 32 | .subcommand(SubCommand::with_name("gen-tests")) |
33 | .subcommand(SubCommand::with_name("install-code")) | 33 | .subcommand(SubCommand::with_name("install-code")) |
34 | .get_matches(); | 34 | .get_matches(); |
35 | let mode = if matches.is_present("verify") { | ||
36 | Verify | ||
37 | } else { | ||
38 | Overwrite | ||
39 | }; | ||
35 | match matches.subcommand() { | 40 | match matches.subcommand() { |
36 | ("install-code", _) => install_code_extension()?, | 41 | ("install-code", _) => install_code_extension()?, |
37 | (name, Some(matches)) => run_gen_command(name, matches.is_present("verify"))?, | 42 | ("gen-tests", _) => gen_tests(mode)?, |
38 | _ => unreachable!(), | 43 | ("gen-kinds", _) => generate(Overwrite)?, |
39 | } | ||
40 | Ok(()) | ||
41 | } | ||
42 | |||
43 | fn run_gen_command(name: &str, verify: bool) -> Result<()> { | ||
44 | match name { | ||
45 | "gen-kinds" => { | ||
46 | update( | ||
47 | &project_root().join(SYNTAX_KINDS), | ||
48 | &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE))?, | ||
49 | verify, | ||
50 | )?; | ||
51 | update( | ||
52 | &project_root().join(AST), | ||
53 | &render_template(&project_root().join(AST_TEMPLATE))?, | ||
54 | verify, | ||
55 | )?; | ||
56 | } | ||
57 | "gen-tests" => gen_tests(verify)?, | ||
58 | _ => unreachable!(), | 44 | _ => unreachable!(), |
59 | } | 45 | } |
60 | Ok(()) | 46 | Ok(()) |
61 | } | 47 | } |
62 | 48 | ||
63 | fn gen_tests(verify: bool) -> Result<()> { | 49 | fn gen_tests(mode: Mode) -> Result<()> { |
64 | let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?; | 50 | let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?; |
65 | 51 | ||
66 | let inline_tests_dir = Path::new(INLINE_TESTS_DIR); | 52 | let inline_tests_dir = Path::new(INLINE_TESTS_DIR); |
@@ -83,7 +69,7 @@ fn gen_tests(verify: bool) -> Result<()> { | |||
83 | inline_tests_dir.join(file_name) | 69 | inline_tests_dir.join(file_name) |
84 | } | 70 | } |
85 | }; | 71 | }; |
86 | update(&path, &test.text, verify)?; | 72 | teraron::update(&path, &test.text, mode)?; |
87 | } | 73 | } |
88 | Ok(()) | 74 | Ok(()) |
89 | } | 75 | } |
diff --git a/crates/tools/tests/cli.rs b/crates/tools/tests/cli.rs index 16899bb5f..0bb5d15d8 100644 --- a/crates/tools/tests/cli.rs +++ b/crates/tools/tests/cli.rs | |||
@@ -1,23 +1,12 @@ | |||
1 | extern crate tools; | 1 | extern crate tools; |
2 | 2 | ||
3 | use tools::{ | 3 | use tools::{ |
4 | project_root, render_template, update, AST, AST_TEMPLATE, SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE, | 4 | generate, Verify |
5 | }; | 5 | }; |
6 | 6 | ||
7 | #[test] | 7 | #[test] |
8 | fn verify_template_generation() { | 8 | fn verify_template_generation() { |
9 | if let Err(error) = update( | 9 | if let Err(error) = generate(Verify) { |
10 | &project_root().join(SYNTAX_KINDS), | ||
11 | &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE)).unwrap(), | ||
12 | true, | ||
13 | ) { | ||
14 | panic!("{}. Please update it by running `cargo gen-kinds`", error); | ||
15 | } | ||
16 | if let Err(error) = update( | ||
17 | &project_root().join(AST), | ||
18 | &render_template(&project_root().join(AST_TEMPLATE)).unwrap(), | ||
19 | true, | ||
20 | ) { | ||
21 | panic!("{}. Please update it by running `cargo gen-kinds`", error); | 10 | panic!("{}. Please update it by running `cargo gen-kinds`", error); |
22 | } | 11 | } |
23 | } | 12 | } |