Finish adding generated parser test generation.
This commit is contained in:
parent
024baf2064
commit
9c43e28f32
8
build.rs
8
build.rs
@ -9,10 +9,8 @@ fn main() -> std::io::Result<()> {
|
|||||||
let out_dir_path = Path::new(&out_dir);
|
let out_dir_path = Path::new(&out_dir);
|
||||||
let parser_tests_dir = out_dir_path.join("src").join("parser").join("tests");
|
let parser_tests_dir = out_dir_path.join("src").join("parser").join("tests");
|
||||||
fs::create_dir_all(&parser_tests_dir)?;
|
fs::create_dir_all(&parser_tests_dir)?;
|
||||||
let files = generate_test_files(Path::new("src/parser/tests"))?;
|
let test_suites_file = generate_test_files(Path::new("src/parser/tests"))?;
|
||||||
for parser_test_file in &files {
|
let file_path = parser_tests_dir.join(&test_suites_file.file_name);
|
||||||
let file_path = parser_tests_dir.join(&parser_test_file.file_name);
|
fs::write(file_path, &test_suites_file.contents)?;
|
||||||
fs::write(file_path, &parser_test_file.contents)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,13 @@ use std::path::Path;
|
|||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
use syn::File;
|
use syn::File;
|
||||||
|
|
||||||
pub struct ParserTestFile {
|
pub struct ParserTestSuitesFile {
|
||||||
pub file_name: String,
|
pub file_name: String,
|
||||||
pub contents: String,
|
pub contents: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>> {
|
pub fn generate_test_files(tests_dir: &Path) -> io::Result<ParserTestSuitesFile> {
|
||||||
let mut files: Vec<ParserTestFile> = vec![];
|
let mut test_suites: Vec<TokenStream> = vec![];
|
||||||
let mut test_module_names: Vec<String> = vec![];
|
|
||||||
|
|
||||||
// generate test file for each sub dir
|
// generate test file for each sub dir
|
||||||
for sub_dir in fs::read_dir(tests_dir)? {
|
for sub_dir in fs::read_dir(tests_dir)? {
|
||||||
@ -21,7 +20,6 @@ pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>>
|
|||||||
if sub_dir_path.is_dir() {
|
if sub_dir_path.is_dir() {
|
||||||
let sub_dir_file_name = sub_dir.file_name();
|
let sub_dir_file_name = sub_dir.file_name();
|
||||||
let sub_dir_string = sub_dir_file_name.to_string_lossy();
|
let sub_dir_string = sub_dir_file_name.to_string_lossy();
|
||||||
test_module_names.push(sub_dir_string.to_string());
|
|
||||||
|
|
||||||
let sub_dir_pascal = sub_dir_string.to_case(Case::Pascal);
|
let sub_dir_pascal = sub_dir_string.to_case(Case::Pascal);
|
||||||
let rule_ident = format_ident!("{}", sub_dir_pascal);
|
let rule_ident = format_ident!("{}", sub_dir_pascal);
|
||||||
@ -45,71 +43,30 @@ pub fn generate_test_files(tests_dir: &Path) -> io::Result<Vec<ParserTestFile>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tests_mod_ident = format_ident!("{}_tests", sub_dir.file_name().to_string_lossy());
|
let tests_mod_ident = format_ident!("{}_tests", sub_dir.file_name().to_string_lossy());
|
||||||
let test_file_contents = quote! {
|
let test_suite = quote! {
|
||||||
#[cfg(test)]
|
|
||||||
mod #tests_mod_ident {
|
mod #tests_mod_ident {
|
||||||
use crate::parser::Rule;
|
use super::*;
|
||||||
use crate::parser::tests::parses_to;
|
|
||||||
|
|
||||||
#(#tests)*
|
#(#tests)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let parsed: File = syn::parse2(test_file_contents).unwrap();
|
test_suites.push(test_suite);
|
||||||
let contents = prettyplease::unparse(&parsed);
|
|
||||||
|
|
||||||
let file_name = sub_dir.file_name().to_string_lossy().to_string() + ".rs";
|
|
||||||
files.push(ParserTestFile {
|
|
||||||
file_name,
|
|
||||||
contents,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
println!("Warning: not a directory: {:?}", sub_dir_path);
|
println!("Warning: not a directory: {:?}", sub_dir_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let test_mod_statements = test_module_names
|
// generate main test_suites file
|
||||||
.iter()
|
let test_suites = quote! {
|
||||||
.map(|name| format_ident!("{}", name))
|
use super::*;
|
||||||
.map(|module_ident| quote! { mod #module_ident; })
|
|
||||||
.collect::<Vec<_>>();
|
#(#test_suites)*
|
||||||
|
|
||||||
// generate main mod.rs file
|
|
||||||
let main_mod = quote! {
|
|
||||||
use crate::parser::DeimosParser;
|
|
||||||
use crate::parser::Rule;
|
|
||||||
use pest_derive::Parser;
|
|
||||||
|
|
||||||
#(#test_mod_statements)*
|
|
||||||
|
|
||||||
pub(crate) fn parses_to(rule: Rule, input: &str) {
|
|
||||||
let parse_result = DeimosParser::parse(rule, input);
|
|
||||||
if let Err(e) = parse_result {
|
|
||||||
panic!("Parsing failed.\n{}", e);
|
|
||||||
} else {
|
|
||||||
let mut pairs = parse_result.unwrap();
|
|
||||||
if input.trim() != pairs.as_str().trim() {
|
|
||||||
panic!(
|
|
||||||
"Parsing did not consume entire input. Consumed only:\n{}",
|
|
||||||
pairs.as_str().trim()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let first = pairs.next().unwrap();
|
|
||||||
if rule != pair.as_rule() {
|
|
||||||
panic!(
|
|
||||||
"Expected {} but found {:?}.",
|
|
||||||
stringify!(rule),
|
|
||||||
pair.as_rule()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let mod_file_parsed: File = syn::parse2(main_mod).unwrap();
|
let test_suites_file: File = syn::parse2(test_suites).unwrap();
|
||||||
let mod_file_contents = prettyplease::unparse(&mod_file_parsed);
|
let test_suites_file_contents = prettyplease::unparse(&test_suites_file);
|
||||||
files.push(ParserTestFile {
|
|
||||||
file_name: String::from("mod.rs"),
|
|
||||||
contents: mod_file_contents,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(files)
|
Ok(ParserTestSuitesFile {
|
||||||
|
file_name: String::from("test_suites.rs"),
|
||||||
|
contents: test_suites_file_contents,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,10 @@ mod deimos_parser_tests {
|
|||||||
match_rule!(first; rule)
|
match_rule!(first; rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod generated_tests {
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/src/parser/tests/test_suites.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hex_int() {
|
fn hex_int() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user