[fine] Dump CSTs and an example zoo
This commit is contained in:
parent
757db0ba3e
commit
1f6d7ec131
9 changed files with 357 additions and 32 deletions
96
fine/build.rs
Normal file
96
fine/build.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use quote::{format_ident, quote};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn generate_test_for_file(path: PathBuf) -> String {
|
||||
let contents = fs::read_to_string(&path).expect("Unable to read input");
|
||||
|
||||
let mut concrete_stuff: Option<String> = None;
|
||||
|
||||
// Start iterating over lines and processing directives....
|
||||
let mut lines = contents.lines();
|
||||
while let Some(line) = lines.next() {
|
||||
let line = match line.strip_prefix("//") {
|
||||
Some(line) => line,
|
||||
None => break,
|
||||
};
|
||||
|
||||
let line = line.trim();
|
||||
if line == "concrete:" {
|
||||
let mut concrete = String::new();
|
||||
while let Some(line) = lines.next() {
|
||||
let line = match line.strip_prefix("// | ") {
|
||||
Some(line) => line,
|
||||
None => break,
|
||||
};
|
||||
|
||||
concrete.push_str(line);
|
||||
concrete.push_str("\n");
|
||||
}
|
||||
concrete_stuff = Some(concrete);
|
||||
}
|
||||
}
|
||||
|
||||
let concrete_comparison = if let Some(concrete) = concrete_stuff {
|
||||
quote! {
|
||||
crate::assert_concrete(&_tree, #concrete)
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let name = format_ident!("{}", path.file_stem().unwrap().to_string_lossy());
|
||||
let test_method = quote! {
|
||||
fn #name() {
|
||||
let (_tree, _lines) = fine::parser::concrete::parse_concrete(#contents);
|
||||
#concrete_comparison;
|
||||
}
|
||||
};
|
||||
|
||||
let syntax_tree = syn::parse2(test_method).unwrap();
|
||||
prettyplease::unparse(&syntax_tree)
|
||||
}
|
||||
|
||||
fn process_directory<T>(output: &mut String, path: T)
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let fine_ext: std::ffi::OsString = "fine".into();
|
||||
let path = path.as_ref();
|
||||
for entry in std::fs::read_dir(path).expect("Unable to read directory") {
|
||||
match entry {
|
||||
Ok(dirent) => {
|
||||
let file_type = dirent.file_type().unwrap();
|
||||
if file_type.is_dir() {
|
||||
let file_name = dirent.file_name();
|
||||
let file_name = file_name.to_string_lossy().to_owned();
|
||||
output.push_str(&format!("mod {file_name} {{\n"));
|
||||
process_directory(output, dirent.path());
|
||||
output.push_str("}\n\n");
|
||||
} else if file_type.is_file() {
|
||||
if dirent.path().extension() == Some(&fine_ext) {
|
||||
output.push_str(&format!("// {}\n", dirent.path().display()));
|
||||
output.push_str("#[test]\n");
|
||||
output.push_str(&generate_test_for_file(dirent.path()));
|
||||
output.push_str("\n\n");
|
||||
}
|
||||
} else {
|
||||
eprintln!("Skipping symlink: {}", path.display());
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Unable to read directory entry: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=./tests");
|
||||
|
||||
let mut test_source = String::new();
|
||||
process_directory(&mut test_source, "./tests");
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("generated_tests.rs");
|
||||
fs::write(dest_path, test_source).unwrap();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue