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 quote::{quote, ToTokens};
use syn::{ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
Field, Token, Type, Token, Type,
}; };
pub(crate) mod attribute; pub(crate) mod attribute;
@ -15,13 +15,6 @@ pub(crate) mod response;
use self::{metadata::Metadata, request::Request, response::Response}; use self::{metadata::Metadata, request::Request, response::Response};
use crate::util; 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. /// The result of processing the `ruma_api` macro, ready for output back to source code.
pub struct Api { pub struct Api {
/// The `metadata` section of the macro. /// The `metadata` section of the macro.

View File

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

View File

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

View File

@ -125,3 +125,12 @@ pub fn derive_string_enum(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemEnum); let input = parse_macro_input!(input as ItemEnum);
expand_all(input).unwrap_or_else(|err| err.to_compile_error()).into() 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 = let input_attrs =
input.attrs.iter().filter(|attr| filter_input_attrs(attr)).collect::<Vec<_>>(); input.attrs.iter().filter(|attr| filter_input_attrs(attr)).collect::<Vec<_>>();