mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-18 10:55:44 +00:00
93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
//! `pest_derive` crate has large dependency tree, and, as a build dependency,
|
|
//! it imposes these deps onto our consumers.
|
|
//!
|
|
//! 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},
|
|
time::Instant,
|
|
};
|
|
|
|
const PREAMBLE: &str = "\
|
|
//! This is @generated code, do not edit by hand.
|
|
//! See `semver.pest` and `genpest.rs`.
|
|
#![allow(unused_attributes)]
|
|
use super::SemverParser;
|
|
";
|
|
|
|
#[test]
|
|
fn generated_code_is_fresh() {
|
|
let t = Instant::now();
|
|
|
|
let token_stream = {
|
|
let grammar = include_str!("../src/semver.pest");
|
|
let input = format!(
|
|
r###"
|
|
#[derive(Parser)]
|
|
#[grammar_inline = r#"{}"#]
|
|
struct SemverParser;
|
|
"###,
|
|
grammar
|
|
)
|
|
.parse::<proc_macro2::TokenStream>()
|
|
.unwrap();
|
|
|
|
let ts = pest_generator::derive_parser(input.into(), true);
|
|
eprintln!("Generated code in {:02?}", t.elapsed());
|
|
ts
|
|
};
|
|
|
|
let current = {
|
|
let current = fs::read("./src/generated.rs").unwrap_or_default();
|
|
String::from_utf8(current).unwrap()
|
|
};
|
|
|
|
let is_up_to_date = {
|
|
let current = normalize(¤t[PREAMBLE.len()..]);
|
|
let generated = normalize(&token_stream.to_string());
|
|
current == generated
|
|
};
|
|
|
|
// Rustfmt takes ages on this input, so fast-path skip it for unchanged
|
|
// code.
|
|
if is_up_to_date {
|
|
return;
|
|
}
|
|
|
|
let code = {
|
|
eprintln!("Reformatting (this will take couple of minutes)");
|
|
let t = Instant::now();
|
|
let code = reformat(&token_stream.to_string());
|
|
let code = format!("{}\n{}", PREAMBLE, code);
|
|
eprintln!("Reformatted in {:02?}", t.elapsed());
|
|
code
|
|
};
|
|
|
|
fs::write("./src/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), "")
|
|
}
|