mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Merge #136
136: Teraro r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
		
						commit
						06ab643b00
					
				
							
								
								
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -794,7 +794,7 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ron"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
version = "0.4.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -1003,7 +1003,7 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "tera"
 | 
			
		||||
version = "0.11.17"
 | 
			
		||||
version = "0.11.18"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -1021,6 +1021,17 @@ dependencies = [
 | 
			
		||||
 "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "teraron"
 | 
			
		||||
version = "0.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "tera 0.11.18 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "termion"
 | 
			
		||||
version = "1.5.1"
 | 
			
		||||
@ -1080,10 +1091,8 @@ version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "tera 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -1345,7 +1354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
 | 
			
		||||
"checksum relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e614f96449605730b4f7ad2c019e88c1652d730634b4eba07b810801856635e3"
 | 
			
		||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 | 
			
		||||
"checksum ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fa11b7a38511d46ff1959ae46ebb60bd8a746f17bdd0206b4c8de7559ac47b"
 | 
			
		||||
"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f"
 | 
			
		||||
"checksum rowan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a1a7366ece9deee5e7df8316a136d585d5c5042854c2297f7f1aee3014c9130"
 | 
			
		||||
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
 | 
			
		||||
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 | 
			
		||||
@ -1371,7 +1380,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
"checksum syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b036b7b35e846707c0e55c2c9441fa47867c0f87fca416921db3261b1d8c741a"
 | 
			
		||||
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
 | 
			
		||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
 | 
			
		||||
"checksum tera 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)" = "2829d259c4699fbbe8acb353d231e6da31ff4301c52244413ed29ff6093da412"
 | 
			
		||||
"checksum tera 0.11.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6c87cae42cc4fc480278c7583792cc5da2d51a25be916b7921cbb45c43063b8d"
 | 
			
		||||
"checksum teraron 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d89ad4617d1dec55331067fadaa041e813479e1779616f3d3ce9308bf46184e"
 | 
			
		||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 | 
			
		||||
"checksum text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc86da66d0b9aa8d359b0ec31b4342c6bc52637eadef05b91b098551a9f8e9"
 | 
			
		||||
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,8 @@ authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
 | 
			
		||||
publish = false
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
ron = "0.3.0"
 | 
			
		||||
teraron = "0.0.1"
 | 
			
		||||
walkdir = "2.1.3"
 | 
			
		||||
itertools = "0.7.8"
 | 
			
		||||
tera = "0.11"
 | 
			
		||||
clap = "2.32.0"
 | 
			
		||||
failure = "0.1.1"
 | 
			
		||||
heck = "0.3.0"
 | 
			
		||||
 | 
			
		||||
@ -1,25 +1,20 @@
 | 
			
		||||
extern crate itertools;
 | 
			
		||||
#[macro_use]
 | 
			
		||||
extern crate failure;
 | 
			
		||||
extern crate heck;
 | 
			
		||||
extern crate ron;
 | 
			
		||||
extern crate tera;
 | 
			
		||||
extern crate teraron;
 | 
			
		||||
 | 
			
		||||
use heck::{CamelCase, ShoutySnakeCase, SnakeCase};
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    fs,
 | 
			
		||||
    path::{Path, PathBuf},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
 | 
			
		||||
pub use teraron::{Mode, Verify, Overwrite};
 | 
			
		||||
 | 
			
		||||
pub type Result<T> = ::std::result::Result<T, failure::Error>;
 | 
			
		||||
 | 
			
		||||
const GRAMMAR: &str = "ra_syntax/src/grammar.ron";
 | 
			
		||||
pub const SYNTAX_KINDS: &str = "ra_syntax/src/syntax_kinds/generated.rs";
 | 
			
		||||
pub const SYNTAX_KINDS_TEMPLATE: &str = "ra_syntax/src/syntax_kinds/generated.rs.tera";
 | 
			
		||||
pub const AST: &str = "ra_syntax/src/ast/generated.rs";
 | 
			
		||||
pub const AST_TEMPLATE: &str = "ra_syntax/src/ast/generated.rs.tera";
 | 
			
		||||
pub const GRAMMAR: &str = "ra_syntax/src/grammar.ron";
 | 
			
		||||
pub const SYNTAX_KINDS: &str = "ra_syntax/src/syntax_kinds/generated.rs.tera";
 | 
			
		||||
pub const AST: &str = "ra_syntax/src/ast/generated.rs.tera";
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Test {
 | 
			
		||||
@ -61,59 +56,23 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> {
 | 
			
		||||
    res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn update(path: &Path, contents: &str, verify: bool) -> Result<()> {
 | 
			
		||||
    match fs::read_to_string(path) {
 | 
			
		||||
        Ok(ref old_contents) if old_contents == contents => {
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        }
 | 
			
		||||
        _ => (),
 | 
			
		||||
    }
 | 
			
		||||
    if verify {
 | 
			
		||||
        bail!("`{}` is not up-to-date", path.display());
 | 
			
		||||
    }
 | 
			
		||||
    eprintln!("updating {}", path.display());
 | 
			
		||||
    fs::write(path, contents)?;
 | 
			
		||||
pub fn generate(mode: Mode) -> Result<()> {
 | 
			
		||||
    let grammar = project_root().join(GRAMMAR);
 | 
			
		||||
    let syntax_kinds = project_root().join(SYNTAX_KINDS);
 | 
			
		||||
    let ast = project_root().join(AST);
 | 
			
		||||
    teraron::generate(
 | 
			
		||||
        &syntax_kinds,
 | 
			
		||||
        &grammar,
 | 
			
		||||
        mode,
 | 
			
		||||
    )?;
 | 
			
		||||
    teraron::generate(
 | 
			
		||||
        &ast,
 | 
			
		||||
        &grammar,
 | 
			
		||||
        mode,
 | 
			
		||||
    )?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn render_template(template: &Path) -> Result<String> {
 | 
			
		||||
    let grammar: ron::value::Value = {
 | 
			
		||||
        let text = fs::read_to_string(project_root().join(GRAMMAR))?;
 | 
			
		||||
        ron::de::from_str(&text)?
 | 
			
		||||
    };
 | 
			
		||||
    let template = fs::read_to_string(template)?;
 | 
			
		||||
    let mut tera = tera::Tera::default();
 | 
			
		||||
    tera.add_raw_template("grammar", &template)
 | 
			
		||||
        .map_err(|e| format_err!("template error: {:?}", e))?;
 | 
			
		||||
    tera.register_function("concat", Box::new(concat));
 | 
			
		||||
    tera.register_filter("camel", |arg, _| {
 | 
			
		||||
        Ok(arg.as_str().unwrap().to_camel_case().into())
 | 
			
		||||
    });
 | 
			
		||||
    tera.register_filter("snake", |arg, _| {
 | 
			
		||||
        Ok(arg.as_str().unwrap().to_snake_case().into())
 | 
			
		||||
    });
 | 
			
		||||
    tera.register_filter("SCREAM", |arg, _| {
 | 
			
		||||
        Ok(arg.as_str().unwrap().to_shouty_snake_case().into())
 | 
			
		||||
    });
 | 
			
		||||
    let ret = tera
 | 
			
		||||
        .render("grammar", &grammar)
 | 
			
		||||
        .map_err(|e| format_err!("template error: {:?}", e))?;
 | 
			
		||||
    return Ok(ret);
 | 
			
		||||
 | 
			
		||||
    fn concat(args: HashMap<String, tera::Value>) -> tera::Result<tera::Value> {
 | 
			
		||||
        let mut elements = Vec::new();
 | 
			
		||||
        for &key in ["a", "b", "c"].iter() {
 | 
			
		||||
            let val = match args.get(key) {
 | 
			
		||||
                Some(val) => val,
 | 
			
		||||
                None => continue,
 | 
			
		||||
            };
 | 
			
		||||
            let val = val.as_array().unwrap();
 | 
			
		||||
            elements.extend(val.iter().cloned());
 | 
			
		||||
        }
 | 
			
		||||
        Ok(tera::Value::Array(elements))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn project_root() -> PathBuf {
 | 
			
		||||
    Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
 | 
			
		||||
        .parent()
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ extern crate clap;
 | 
			
		||||
extern crate failure;
 | 
			
		||||
extern crate tools;
 | 
			
		||||
extern crate walkdir;
 | 
			
		||||
extern crate teraron;
 | 
			
		||||
 | 
			
		||||
use clap::{App, Arg, SubCommand};
 | 
			
		||||
use std::{
 | 
			
		||||
@ -12,8 +13,7 @@ use std::{
 | 
			
		||||
    process::Command,
 | 
			
		||||
};
 | 
			
		||||
use tools::{
 | 
			
		||||
    collect_tests, project_root, render_template, update, Result, Test, AST, AST_TEMPLATE,
 | 
			
		||||
    SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE,
 | 
			
		||||
    collect_tests, Result, Test, generate, Mode, Overwrite, Verify,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar";
 | 
			
		||||
@ -32,35 +32,21 @@ fn main() -> Result<()> {
 | 
			
		||||
        .subcommand(SubCommand::with_name("gen-tests"))
 | 
			
		||||
        .subcommand(SubCommand::with_name("install-code"))
 | 
			
		||||
        .get_matches();
 | 
			
		||||
    let mode = if matches.is_present("verify") {
 | 
			
		||||
        Verify
 | 
			
		||||
    } else {
 | 
			
		||||
        Overwrite
 | 
			
		||||
    };
 | 
			
		||||
    match matches.subcommand() {
 | 
			
		||||
        ("install-code", _) => install_code_extension()?,
 | 
			
		||||
        (name, Some(matches)) => run_gen_command(name, matches.is_present("verify"))?,
 | 
			
		||||
        ("gen-tests", _) => gen_tests(mode)?,
 | 
			
		||||
        ("gen-kinds", _) => generate(Overwrite)?,
 | 
			
		||||
        _ => unreachable!(),
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn run_gen_command(name: &str, verify: bool) -> Result<()> {
 | 
			
		||||
    match name {
 | 
			
		||||
        "gen-kinds" => {
 | 
			
		||||
            update(
 | 
			
		||||
                &project_root().join(SYNTAX_KINDS),
 | 
			
		||||
                &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE))?,
 | 
			
		||||
                verify,
 | 
			
		||||
            )?;
 | 
			
		||||
            update(
 | 
			
		||||
                &project_root().join(AST),
 | 
			
		||||
                &render_template(&project_root().join(AST_TEMPLATE))?,
 | 
			
		||||
                verify,
 | 
			
		||||
            )?;
 | 
			
		||||
        }
 | 
			
		||||
        "gen-tests" => gen_tests(verify)?,
 | 
			
		||||
        _ => unreachable!(),
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn gen_tests(verify: bool) -> Result<()> {
 | 
			
		||||
fn gen_tests(mode: Mode) -> Result<()> {
 | 
			
		||||
    let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?;
 | 
			
		||||
 | 
			
		||||
    let inline_tests_dir = Path::new(INLINE_TESTS_DIR);
 | 
			
		||||
@ -83,7 +69,7 @@ fn gen_tests(verify: bool) -> Result<()> {
 | 
			
		||||
                inline_tests_dir.join(file_name)
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        update(&path, &test.text, verify)?;
 | 
			
		||||
        teraron::update(&path, &test.text, mode)?;
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,12 @@
 | 
			
		||||
extern crate tools;
 | 
			
		||||
 | 
			
		||||
use tools::{
 | 
			
		||||
    project_root, render_template, update, AST, AST_TEMPLATE, SYNTAX_KINDS, SYNTAX_KINDS_TEMPLATE,
 | 
			
		||||
    generate, Verify
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn verify_template_generation() {
 | 
			
		||||
    if let Err(error) = update(
 | 
			
		||||
        &project_root().join(SYNTAX_KINDS),
 | 
			
		||||
        &render_template(&project_root().join(SYNTAX_KINDS_TEMPLATE)).unwrap(),
 | 
			
		||||
        true,
 | 
			
		||||
    ) {
 | 
			
		||||
        panic!("{}. Please update it by running `cargo gen-kinds`", error);
 | 
			
		||||
    }
 | 
			
		||||
    if let Err(error) = update(
 | 
			
		||||
        &project_root().join(AST),
 | 
			
		||||
        &render_template(&project_root().join(AST_TEMPLATE)).unwrap(),
 | 
			
		||||
        true,
 | 
			
		||||
    ) {
 | 
			
		||||
    if let Err(error) = generate(Verify) {
 | 
			
		||||
        panic!("{}. Please update it by running `cargo gen-kinds`", error);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user