macros: Allow opt-out of Debug deriving for incoming types

This commit is contained in:
Jonas Platte 2022-10-17 14:50:54 +02:00
parent fba6f70c2d
commit cc514a2b6c
No known key found for this signature in database
GPG Key ID: AAA7A61F696C3E0C
2 changed files with 39 additions and 24 deletions

View File

@ -261,6 +261,10 @@ pub fn user_id(input: TokenStream) -> TokenStream {
/// Generating an 'Incoming' version of the type this derive macro is used on. /// Generating an 'Incoming' version of the type this derive macro is used on.
/// ///
/// This type will be a fully-owned version of the input type, using no lifetime generics. /// This type will be a fully-owned version of the input type, using no lifetime generics.
///
/// By default, the generated type will derive `Debug` and `serde::Deserialize`. To derive
/// additional traits, use `#[incoming_derive(ExtraDeriveMacro)]`. To disable the default derives,
/// use `#[incoming_derive(!Debug, !Deserialize)]`.
#[proc_macro_derive(Incoming, attributes(incoming_derive))] #[proc_macro_derive(Incoming, attributes(incoming_derive))]
pub fn derive_incoming(input: TokenStream) -> TokenStream { pub fn derive_incoming(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);

View File

@ -59,27 +59,35 @@ pub fn expand_derive_incoming(mut ty_def: DeriveInput) -> syn::Result<TokenStrea
}); });
} }
let mut derives = vec![quote! { Debug }]; let meta: Vec<Meta> = ty_def
let mut derive_deserialize = true;
derives.extend(
ty_def
.attrs .attrs
.iter() .iter()
.filter(|attr| attr.path.is_ident("incoming_derive")) .filter(|attr| attr.path.is_ident("incoming_derive"))
.map(|attr| attr.parse_args()) .map(|attr| attr.parse_args())
.collect::<syn::Result<Vec<Meta>>>()? .collect::<syn::Result<_>>()?;
let mut derive_debug = true;
let mut derive_deserialize = true;
let mut derives: Vec<_> = meta
.into_iter() .into_iter()
.flat_map(|meta| meta.derive_macs) .flat_map(|m| m.derive_macs)
.filter_map(|derive_mac| match derive_mac { .filter_map(|derive_mac| match derive_mac {
DeriveMac::Regular(id) => Some(quote! { #id }), DeriveMac::Regular(id) => Some(quote! { #id }),
DeriveMac::NegativeDebug => {
derive_debug = false;
None
}
DeriveMac::NegativeDeserialize => { DeriveMac::NegativeDeserialize => {
derive_deserialize = false; derive_deserialize = false;
None None
} }
}), })
); .collect();
if derive_debug {
derives.push(quote! { ::std::fmt::Debug });
}
derives.push(if derive_deserialize { derives.push(if derive_deserialize {
quote! { #ruma_common::exports::serde::Deserialize } quote! { #ruma_common::exports::serde::Deserialize }
} else { } else {
@ -265,6 +273,7 @@ impl Parse for Meta {
pub enum DeriveMac { pub enum DeriveMac {
Regular(Path), Regular(Path),
NegativeDebug,
NegativeDeserialize, NegativeDeserialize,
} }
@ -274,14 +283,16 @@ impl Parse for DeriveMac {
let _: Token![!] = input.parse()?; let _: Token![!] = input.parse()?;
let mac: Ident = input.parse()?; let mac: Ident = input.parse()?;
if mac != "Deserialize" { if mac == "Debug" {
return Err(syn::Error::new_spanned( Ok(Self::NegativeDebug)
mac, } else if mac == "Deserialize" {
"Negative incoming_derive can only be used for Deserialize",
));
}
Ok(Self::NegativeDeserialize) Ok(Self::NegativeDeserialize)
} else {
Err(syn::Error::new_spanned(
mac,
"Negative incoming_derive can only be used for Debug and Deserialize",
))
}
} else { } else {
let mac = input.parse()?; let mac = input.parse()?;
Ok(Self::Regular(mac)) Ok(Self::Regular(mac))