Files
lighthouse/common/test_random_derive/src/lib.rs
Mac L 32f7615cc8 Update syn to 2.0.110 (#8563)
#8547


  We are currently using an older version of `syn` in `test_random_derive`. Updating this removes one of the sources of `syn` `1.0.109` in our dependency tree.


Co-Authored-By: Mac L <mjladson@pm.me>

Co-Authored-By: Michael Sproul <michaelsproul@users.noreply.github.com>
2025-12-15 03:20:12 +00:00

60 lines
2.0 KiB
Rust

use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};
/// Returns true if some field has an attribute declaring it should be generated from default (not
/// randomized).
///
/// The field attribute is: `#[test_random(default)]`
fn should_use_default(field: &syn::Field) -> bool {
field.attrs.iter().any(|attr| {
attr.path().is_ident("test_random")
&& matches!(&attr.meta, syn::Meta::List(list) if list.tokens.to_string().replace(' ', "") == "default")
})
}
#[proc_macro_derive(TestRandom, attributes(test_random))]
pub fn test_random_derive(input: TokenStream) -> TokenStream {
let derived_input = parse_macro_input!(input as DeriveInput);
let name = &derived_input.ident;
let (impl_generics, ty_generics, where_clause) = &derived_input.generics.split_for_impl();
let syn::Data::Struct(struct_data) = &derived_input.data else {
panic!("test_random_derive only supports structs.");
};
// Build quotes for fields that should be generated and those that should be built from
// `Default`.
let mut quotes = vec![];
for field in &struct_data.fields {
match &field.ident {
Some(ident) => {
if should_use_default(field) {
quotes.push(quote! {
#ident: <_>::default(),
});
} else {
quotes.push(quote! {
#ident: <_>::random_for_test(rng),
});
}
}
_ => panic!("test_random_derive only supports named struct fields."),
};
}
let output = quote! {
impl #impl_generics TestRandom for #name #ty_generics #where_clause {
fn random_for_test(rng: &mut impl rand::RngCore) -> Self {
Self {
#(
#quotes
)*
}
}
}
};
output.into()
}