diff --git a/CHANGELOG.md b/CHANGELOG.md index 152e21db..c706ddd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +* Only copy across `"doc", "cfg", "allow", "deny"` attributes from main enum variants to discriminant variants. [#73](https://github.com/Peternator7/strum/issues/73) + ## 0.17.1 * Fixed an issue caused by combining [#60](https://github.com/Peternator7/strum/pull/60) and [#76](https://github.com/Peternator7/strum/pull/76) diff --git a/strum_macros/src/macros/enum_discriminants.rs b/strum_macros/src/macros/enum_discriminants.rs index ff16b881..5191cb3c 100644 --- a/strum_macros/src/macros/enum_discriminants.rs +++ b/strum_macros/src/macros/enum_discriminants.rs @@ -4,6 +4,12 @@ use syn; use helpers::extract_meta; +/// Attributes to copy from the main enum's variants to the discriminant enum's variants. +/// +/// Attributes not in this list may be for other `proc_macro`s on the main enum, and may cause +/// compilation problems when copied across. +const ATTRIBUTES_TO_COPY: &[&str] = &["doc", "cfg", "allow", "deny"]; + pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let vis = &ast.vis; @@ -66,9 +72,9 @@ pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream { // Don't copy across the "strum" meta attribute. let attrs = variant.attrs.iter().filter(|attr| { - attr.parse_meta() - .map(|meta| !meta.path().is_ident("strum")) - .unwrap_or(true) + ATTRIBUTES_TO_COPY + .iter() + .any(|attr_whitelisted| attr.path.is_ident(attr_whitelisted)) }); discriminants.push(quote! { #(#attrs)* #ident }); diff --git a/strum_tests/Cargo.toml b/strum_tests/Cargo.toml index aae5f2da..b47b2971 100644 --- a/strum_tests/Cargo.toml +++ b/strum_tests/Cargo.toml @@ -7,4 +7,5 @@ authors = ["Peter Glotfelty "] strum = { path = "../strum", features = ["derive"] } strum_macros = { path = "../strum_macros", features = [] } clap = "2.33.0" +enum_variant_type = "0.2.0" structopt = "0.2.18" diff --git a/strum_tests/tests/enum_discriminants.rs b/strum_tests/tests/enum_discriminants.rs index a0b3f460..0f341d4d 100644 --- a/strum_tests/tests/enum_discriminants.rs +++ b/strum_tests/tests/enum_discriminants.rs @@ -1,6 +1,8 @@ extern crate strum; #[macro_use] extern crate strum_macros; +#[macro_use] +extern crate enum_variant_type; use strum::IntoEnumIterator; @@ -184,3 +186,35 @@ fn from_ref_test_complex() { let rara = Rara; assert_eq!(EnumIntoComplexVars::A, (&EnumIntoComplex::A(&rara)).into()); } + +#[allow(dead_code)] +#[derive(Debug, Eq, PartialEq, EnumDiscriminants, EnumVariantType)] +#[strum_discriminants( + name(VariantFilterAttrDiscs), + derive(Display, EnumIter, EnumString), + strum(serialize_all = "snake_case") +)] +enum VariantFilterAttr { + #[evt(derive(Clone, Copy, Debug))] + DarkBlack(bool), + #[evt(skip)] + BrightWhite(i32), +} + +#[test] +fn filter_variant_attributes_pass_through() { + use std::str::FromStr; + + let discriminants = VariantFilterAttrDiscs::iter().collect::>(); + let expected = vec![ + VariantFilterAttrDiscs::DarkBlack, + VariantFilterAttrDiscs::BrightWhite, + ]; + + assert_eq!(expected, discriminants); + assert_eq!("dark_black", VariantFilterAttrDiscs::DarkBlack.to_string()); + assert_eq!( + VariantFilterAttrDiscs::DarkBlack, + VariantFilterAttrDiscs::from_str("dark_black").unwrap() + ); +}