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