diff --git a/strum_macros/src/helpers/metadata.rs b/strum_macros/src/helpers/metadata.rs index 62262e13..558b9406 100644 --- a/strum_macros/src/helpers/metadata.rs +++ b/strum_macros/src/helpers/metadata.rs @@ -3,8 +3,8 @@ use syn::{ parse::{Parse, ParseStream}, parse2, parse_str, punctuated::Punctuated, - Attribute, DeriveInput, Expr, ExprLit, Field, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue, - Path, Token, Variant, Visibility, + Attribute, DeriveInput, Expr, ExprLit, Field, Ident, Lit, LitBool, LitStr, Meta, MetaList, + MetaNameValue, Path, Token, Variant, Visibility, }; use super::case_style::CaseStyle; @@ -27,6 +27,7 @@ pub mod kw { custom_keyword!(name); custom_keyword!(vis); custom_keyword!(doc); + custom_keyword!(attributes); // variant metadata custom_keyword!(message); @@ -125,6 +126,7 @@ pub enum EnumDiscriminantsMeta { Derive { _kw: kw::derive, paths: Vec }, Name { kw: kw::name, name: Ident }, Vis { kw: kw::vis, vis: Visibility }, + Attributes { _kw: kw::attributes, attributes: Vec }, Other { passthrough_meta: Meta }, } @@ -151,6 +153,15 @@ impl Parse for EnumDiscriminantsMeta { parenthesized!(content in input); let vis = content.parse()?; Ok(EnumDiscriminantsMeta::Vis { kw, vis }) + } else if input.peek(kw::attributes) { + let _kw = input.parse()?; + let content; + parenthesized!(content in input); + let attributes = content.parse_terminated(MetaList::parse, Token![,])?; + Ok(EnumDiscriminantsMeta::Attributes { + _kw, + attributes: attributes.into_iter().collect(), + }) } else { let passthrough_meta = input.parse()?; Ok(EnumDiscriminantsMeta::Other { passthrough_meta }) diff --git a/strum_macros/src/helpers/type_props.rs b/strum_macros/src/helpers/type_props.rs index 60ffa22c..7763e574 100644 --- a/strum_macros/src/helpers/type_props.rs +++ b/strum_macros/src/helpers/type_props.rs @@ -1,6 +1,6 @@ use proc_macro2::TokenStream; use std::default::Default; -use syn::{parse_quote, DeriveInput, Ident, LitStr, Meta, Path, Visibility}; +use syn::{parse_quote, DeriveInput, Ident, LitStr, Meta, MetaList, Path, Visibility}; use super::case_style::CaseStyle; use super::metadata::{DeriveInputExt, EnumDiscriminantsMeta, EnumMeta}; @@ -21,6 +21,7 @@ pub struct StrumTypeProperties { pub discriminant_name: Option, pub discriminant_others: Vec, pub discriminant_vis: Option, + pub discriminant_attributes: Vec, pub use_phf: bool, pub prefix: Option, pub suffix: Option, @@ -148,6 +149,9 @@ impl HasTypeProperties for DeriveInput { vis_kw = Some(kw); output.discriminant_vis = Some(vis); } + EnumDiscriminantsMeta::Attributes { attributes, .. } => { + output.discriminant_attributes.extend(attributes); + } EnumDiscriminantsMeta::Other { passthrough_meta } => { output.discriminant_others.push(passthrough_meta); } diff --git a/strum_macros/src/macros/enum_discriminants.rs b/strum_macros/src/macros/enum_discriminants.rs index e6a93780..2bc35d07 100644 --- a/strum_macros/src/macros/enum_discriminants.rs +++ b/strum_macros/src/macros/enum_discriminants.rs @@ -1,6 +1,6 @@ use proc_macro2::{Span, TokenStream, TokenTree}; use quote::{quote, ToTokens}; -use syn::parse_quote; +use syn::{parse_quote, MetaList}; use syn::{Data, DeriveInput, Fields}; use crate::helpers::{non_enum_error, strum_discriminants_passthrough_error, HasTypeProperties}; @@ -20,8 +20,23 @@ pub fn enum_discriminants_inner(ast: &DeriveInput) -> syn::Result { _ => return Err(non_enum_error()), }; - // Derives for the generated enum let type_properties = ast.get_type_properties()?; + + // Attributes for the generated enum + let attributes: &Vec = &type_properties.discriminant_attributes; + + let attributes: Vec<_> = attributes + .iter() + .map(|a| { + quote! { + #[#a] + } + }) + .collect(); + + let attributes = quote! {#(#attributes)*}; + + // Derives for the generated enum let strum_module_path = type_properties.crate_module_path(); let mut derives = type_properties.discriminant_derives; @@ -223,6 +238,7 @@ pub fn enum_discriminants_inner(ast: &DeriveInput) -> syn::Result { }; Ok(quote! { + #attributes #derives #repr #(#[ #pass_through_attributes ])*