Merge pull request #1062 from rsdy/test-codegen

Resurrect code generation through tests
This commit is contained in:
Sunli 2022-09-06 14:42:25 +08:00 committed by GitHub
commit e40823f16b
4 changed files with 2207 additions and 34 deletions

View File

@ -17,6 +17,6 @@ pest = "2.2.1"
serde = { version = "1.0.125", features = ["derive"] }
serde_json = "1.0.64"
[build-dependencies]
[dev-dependencies]
pest_generator = "2.2.1"
proc-macro2 = "1.0.37"

View File

@ -1,32 +0,0 @@
use std::{error::Error, fs};
const PREAMBLE: &str = "\
//! This is @generated code, do not edit by hand.
//! See `graphql.pest` and `tests/codegen.rs`.
#![allow(unused_attributes)]
use super::GraphQLParser;
";
fn main() -> Result<(), Box<dyn Error>> {
generated_code()?;
println!("cargo:rerun-if-changed=src/graphql.pest");
Ok(())
}
fn generated_code() -> Result<(), Box<dyn Error>> {
let input = r###"
#[derive(Parser)]
#[grammar = r#"graphql.pest"#]
struct GraphQLParser;
"###
.parse::<proc_macro2::TokenStream>()
.unwrap();
let tokens = pest_generator::derive_parser(input, false);
let new = tokens.to_string();
let code = format!("{}\n{}", PREAMBLE, &new);
let current_code = fs::read_to_string("./src/parse/generated.rs").unwrap();
if current_code != code {
fs::write("./src/parse/generated.rs", code).unwrap();
}
Ok(())
}

File diff suppressed because one or more lines are too long

View File

@ -3,3 +3,70 @@
//!
//! To avoid that, let's just dump generated code to string into this
//! repository, and add a test that checks that the code is fresh.
use std::{
fs,
io::Write,
process::{Command, Stdio},
};
const PREAMBLE: &str = r#"
//! This is @generated code, do not edit by hand.
//! See `graphql.pest` and `tests/codegen.rs`.
#![allow(unused_attributes)]
use super::GraphQLParser;
"#;
#[test]
fn generated_code_is_fresh() {
let input = format!(
r###"
#[derive(Parser)]
#[grammar = r#"graphql.pest"#]
struct GraphQLParser;
"###,
)
.parse::<proc_macro2::TokenStream>()
.unwrap();
let tokens = pest_generator::derive_parser(input.into(), false);
let current =
String::from_utf8(fs::read("./src/parse/generated.rs").unwrap_or_default()).unwrap();
let current_content = match current.len() > PREAMBLE.len() {
true => &current[PREAMBLE.len()..],
false => current.as_str(),
};
let new = tokens.to_string();
let is_up_to_date = normalize(&current_content) == normalize(&new);
if is_up_to_date {
return;
}
let code = format!("{}\n{}", PREAMBLE, reformat(&new));
fs::write("./src/parse/generated.rs", code).unwrap();
panic!("Generated code in the repository is outdated, updating...");
}
fn reformat(code: &str) -> String {
let mut cmd = Command::new("rustfmt")
.args(&["--config", "tab_spaces=2"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
cmd.stdin
.take()
.unwrap()
.write_all(code.as_bytes())
.unwrap();
let output = cmd.wait_with_output().unwrap();
assert!(output.status.success());
String::from_utf8(output.stdout).unwrap()
}
fn normalize(code: &str) -> String {
code.replace(|c: char| c.is_ascii_whitespace() || "{},".contains(c), "")
}