Stop stripping serde attributes

To still prevent 'unknown attribute' errors, the attribute is registered
using a dummy derive macro where needed.
This commit is contained in:
Jonas Platte 2020-12-13 11:54:33 +01:00
parent e8b1e35714
commit ae6595339c
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
5 changed files with 22 additions and 26 deletions

View File

@ -4,7 +4,7 @@ use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{
parse::{Parse, ParseStream},
Field, Token, Type,
Token, Type,
};
pub(crate) mod attribute;
@ -15,13 +15,6 @@ pub(crate) mod response;
use self::{metadata::Metadata, request::Request, response::Response};
use crate::util;
/// Removes `serde` attributes from struct fields.
pub fn strip_serde_attrs(field: &Field) -> Field {
let mut field = field.clone();
field.attrs.retain(|attr| !attr.path.is_ident("serde"));
field
}
/// The result of processing the `ruma_api` macro, ready for output back to source code.
pub struct Api {
/// The `metadata` section of the macro.

View File

@ -12,10 +12,7 @@ use syn::{
};
use crate::{
api::{
attribute::{Meta, MetaNameValue},
strip_serde_attrs,
},
api::attribute::{Meta, MetaNameValue},
util,
};
@ -450,8 +447,7 @@ impl ToTokens for Request {
let request_def = if self.fields.is_empty() {
quote!(;)
} else {
let fields =
self.fields.iter().map(|request_field| strip_serde_attrs(request_field.field()));
let fields = self.fields.iter().map(|request_field| request_field.field());
quote! { { #(#fields),* } }
};
@ -540,7 +536,7 @@ impl ToTokens for Request {
};
let request = quote! {
#[derive(Debug, Clone, #ruma_serde::Outgoing)]
#[derive(Debug, Clone, #ruma_serde::Outgoing, #ruma_serde::_FakeDeriveSerde)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize)]
#( #struct_attributes )*

View File

@ -12,10 +12,7 @@ use syn::{
};
use crate::{
api::{
attribute::{Meta, MetaNameValue},
strip_serde_attrs,
},
api::attribute::{Meta, MetaNameValue},
util,
};
@ -320,9 +317,7 @@ impl ToTokens for Response {
let response_def = if self.fields.is_empty() {
quote!(;)
} else {
let fields =
self.fields.iter().map(|response_field| strip_serde_attrs(response_field.field()));
let fields = self.fields.iter().map(|response_field| response_field.field());
quote! { { #(#fields),* } }
};
@ -347,7 +342,7 @@ impl ToTokens for Response {
};
let response = quote! {
#[derive(Debug, Clone, #ruma_serde::Outgoing)]
#[derive(Debug, Clone, #ruma_serde::Outgoing, #ruma_serde::_FakeDeriveSerde)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize)]
#( #struct_attributes )*

View File

@ -125,3 +125,12 @@ pub fn derive_string_enum(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemEnum);
expand_all(input).unwrap_or_else(|err| err.to_compile_error()).into()
}
/// A derive macro that generates no code, but registers the serde attribute so both `#[serde(...)]`
/// and `#[cfg_attr(..., serde(...))]` are accepted on the type, its fields and (in case the input
/// is an enum) variants fields.
#[doc(hidden)]
#[proc_macro_derive(_FakeDeriveSerde, attributes(serde))]
pub fn fake_derive_serde(_input: TokenStream) -> TokenStream {
TokenStream::new()
}

View File

@ -45,9 +45,12 @@ pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
}
}),
);
if derive_deserialize {
derives.push(quote! { #ruma_serde::exports::serde::Deserialize });
}
derives.push(if derive_deserialize {
quote! { #ruma_serde::exports::serde::Deserialize }
} else {
quote! { #ruma_serde::_FakeDeriveSerde }
});
let input_attrs =
input.attrs.iter().filter(|attr| filter_input_attrs(attr)).collect::<Vec<_>>();