Add default
attribute to TestRandom
derive.
Allows for generating the item from default instead of randomizing it.
This commit is contained in:
parent
f739bb5551
commit
01bfd38637
@ -4,7 +4,20 @@ use crate::proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(TestRandom)]
|
||||
/// 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 {
|
||||
for attr in &field.attrs {
|
||||
if attr.tts.to_string() == "( default )" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[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;
|
||||
@ -14,14 +27,32 @@ pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
||||
_ => panic!("test_random_derive only supports structs."),
|
||||
};
|
||||
|
||||
let field_names = get_named_field_idents(&struct_data);
|
||||
// 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(ref 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<T: RngCore> TestRandom<T> for #name {
|
||||
fn random_for_test(rng: &mut T) -> Self {
|
||||
Self {
|
||||
#(
|
||||
#field_names: <_>::random_for_test(rng),
|
||||
#quotes
|
||||
)*
|
||||
}
|
||||
}
|
||||
@ -30,14 +61,3 @@ pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
||||
|
||||
output.into()
|
||||
}
|
||||
|
||||
fn get_named_field_idents(struct_data: &syn::DataStruct) -> Vec<(&syn::Ident)> {
|
||||
struct_data
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| match &f.ident {
|
||||
Some(ref ident) => ident,
|
||||
_ => panic!("test_random_derive only supports named struct fields."),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user