96 lines
3.2 KiB
Rust
96 lines
3.2 KiB
Rust
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();
|
|
}
|