diff --git a/string-cache-codegen/Cargo.toml b/string-cache-codegen/Cargo.toml index 11a5b52..d27e489 100644 --- a/string-cache-codegen/Cargo.toml +++ b/string-cache-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "string_cache_codegen" -version = "0.11.1" # Also update ../README.md when making a semver-breaking change +version = "0.11.2" # Also update ../README.md when making a semver-breaking change authors = [ "The Servo Project Developers" ] description = "A codegen library for string-cache, developed as part of the Servo project." license = "MIT OR Apache-2.0" diff --git a/string-cache-codegen/lib.rs b/string-cache-codegen/lib.rs index 6f01343..2cbd0f3 100644 --- a/string-cache-codegen/lib.rs +++ b/string-cache-codegen/lib.rs @@ -68,7 +68,7 @@ use proc_macro2::Ident; use quote::quote; use std::collections::BTreeSet; use std::fs::File; -use std::io::{self, BufWriter, Write}; +use std::io::{self, BufWriter, Read, Write}; use std::path::Path; /// A builder for a static atom set and relevant macros @@ -166,16 +166,41 @@ impl AtomType { where W: Write, { - destination.write_all( - self.to_tokens() - .to_string() - // Insert some newlines to make the generated code slightly easier to read. - .replace(" [ \"", "[\n\"") - .replace("\" , ", "\",\n") - .replace(" ( \"", "\n( \"") - .replace("; ", ";\n") - .as_bytes(), - ) + let unformatted = self.to_tokens().to_string(); + if let Ok(formatted) = Self::rustfmt(&unformatted) { + destination.write_all(&formatted) + } else { + // Maybe rustfmt isn’t installed + destination.write_all(unformatted.as_bytes()) + } + } + + fn rustfmt(unformatted: &str) -> Result, std::io::Error> { + if cfg!(miri) { + // Miri does’t support `Command::spawn` as of rustc 1.100.0-nightly (4b6d04e70 2026-09-13): + // ``` + // error: unsupported operation: can't call foreign function `posix_spawnattr_init` on OS `linux` + // ``` + return Err(std::io::Error::other("rustfmt skipped for miri")); + } + let mut process = std::process::Command::new("rustfmt") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn()?; + let mut child_stdin = process.stdin.take().unwrap(); + child_stdin.write_all(unformatted.as_bytes())?; + child_stdin.flush()?; + drop(child_stdin); + let mut formatted = Vec::new(); + process.stdout.take().unwrap().read_to_end(&mut formatted)?; + let status = process.wait()?; + if status.success() { + Ok(formatted) + } else { + Err(std::io::Error::other(format!( + "rustfmt exited with status {status:?}" + ))) + } } #[cfg(test)] @@ -183,16 +208,7 @@ impl AtomType { /// /// Used mostly for testing or displaying a value. pub fn write_to_string(&mut self, mut destination: Vec) -> io::Result { - destination.write_all( - self.to_tokens() - .to_string() - // Insert some newlines to make the generated code slightly easier to read. - .replace(" [ \"", "[\n\"") - .replace("\" , ", "\",\n") - .replace(" ( \"", "\n( \"") - .replace("; ", ";\n") - .as_bytes(), - )?; + self.write_to(&mut destination)?; let str = String::from_utf8(destination).unwrap(); Ok(str) }