Support multiple attribute arguments in ruma_event attribute (#161)

* Add parsing to allow ruma_event attribute to accept mutli args

* fixup! Add parsing to allow ruma_event attribute to accept mutli args

* Refactor MetaAttrs::parse and resolve review issues
This commit is contained in:
Devin Ragotzy 2020-07-26 19:18:28 -04:00 committed by GitHub
parent 1862d15365
commit 4a34375449
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 13 deletions

View File

@ -56,6 +56,25 @@ impl Parse for EventMeta {
}
}
struct MetaAttrs(Vec<EventMeta>);
impl MetaAttrs {
fn is_custom(&self) -> bool {
self.0.iter().any(|a| a == &EventMeta::CustomRedacted)
}
fn get_event_type(&self) -> Option<&LitStr> {
self.0.iter().find_map(|a| a.get_event_type())
}
}
impl Parse for MetaAttrs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let attrs = syn::punctuated::Punctuated::<EventMeta, Token![,]>::parse_terminated(input)?;
Ok(Self(attrs.into_iter().collect()))
}
}
/// Create an `EventContent` implementation for a struct.
pub fn expand_event_content(input: &DeriveInput, emit_redacted: bool) -> syn::Result<TokenStream> {
let ident = &input.ident;
@ -64,7 +83,7 @@ pub fn expand_event_content(input: &DeriveInput, emit_redacted: bool) -> syn::Re
.attrs
.iter()
.filter(|attr| attr.path.is_ident("ruma_event"))
.map(|attr| attr.parse_args::<EventMeta>())
.map(|attr| attr.parse_args::<MetaAttrs>())
.collect::<syn::Result<Vec<_>>>()?;
let event_type = content_attr.iter().find_map(|a| a.get_event_type()).ok_or_else(|| {
@ -75,7 +94,7 @@ pub fn expand_event_content(input: &DeriveInput, emit_redacted: bool) -> syn::Re
syn::Error::new(Span::call_site(), msg)
})?;
let redacted = if emit_redacted && needs_redacted(input) {
let redacted = if emit_redacted && needs_redacted(&content_attr) {
let doc = format!("The payload for a redacted `{}`", ident);
let redacted_ident = format_ident!("Redacted{}", ident);
let kept_redacted_fields = if let syn::Data::Struct(syn::DataStruct {
@ -238,7 +257,7 @@ pub fn expand_message_event_content(input: &DeriveInput) -> syn::Result<TokenStr
let ident = input.ident.clone();
let room_ev_content = expand_room_event_content(input)?;
let redacted_marker_trait = if needs_redacted(input) {
let redacted_marker_trait = if needs_redacted_from_input(input) {
let ident = format_ident!("Redacted{}", &ident);
quote! {
impl ::ruma_events::RedactedMessageEventContent for #ident { }
@ -261,7 +280,7 @@ pub fn expand_state_event_content(input: &DeriveInput) -> syn::Result<TokenStrea
let ident = input.ident.clone();
let room_ev_content = expand_room_event_content(input)?;
let redacted_marker_trait = if needs_redacted(input) {
let redacted_marker_trait = if needs_redacted_from_input(input) {
let ident = format_ident!("Redacted{}", input.ident);
quote! {
impl ::ruma_events::RedactedStateEventContent for #ident { }
@ -302,11 +321,13 @@ fn generate_event_content_impl(ident: &Ident, event_type: &LitStr) -> TokenStrea
}
}
fn needs_redacted(input: &DeriveInput) -> bool {
input
.attrs
.iter()
.flat_map(|a| a.parse_args::<EventMeta>().ok())
.find(|a| a == &EventMeta::CustomRedacted)
.is_none()
fn needs_redacted(input: &[MetaAttrs]) -> bool {
// `is_custom` means that the content struct does not need a generated
// redacted struct also. If no `custom_redacted` attrs are found the content
// needs a redacted struct generated.
!input.iter().any(|a| a.is_custom())
}
fn needs_redacted_from_input(input: &DeriveInput) -> bool {
!input.attrs.iter().flat_map(|a| a.parse_args::<MetaAttrs>().ok()).any(|a| a.is_custom())
}

View File

@ -15,8 +15,7 @@ pub type AliasesEvent = StateEvent<AliasesEventContent>;
/// The payload for `AliasesEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)]
#[non_exhaustive]
#[ruma_event(type = "m.room.aliases")]
#[ruma_event(custom_redacted)]
#[ruma_event(type = "m.room.aliases", custom_redacted)]
pub struct AliasesEventContent {
/// A list of room aliases.
pub aliases: Vec<RoomAliasId>,