Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding visibility option vis(...) to #[strum_discriminants] (#137) #138

Merged
merged 8 commits into from
Nov 16, 2020
11 changes: 10 additions & 1 deletion strum_macros/src/helpers/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
spanned::Spanned,
Attribute, DeriveInput, Ident, LitStr, Path, Token, Variant,
Attribute, DeriveInput, Ident, LitStr, Path, Token, Variant, Visibility,
};

use super::case_style::CaseStyle;
Expand All @@ -18,6 +18,7 @@ pub mod kw {
// enum discriminant metadata
custom_keyword!(derive);
custom_keyword!(name);
custom_keyword!(vis);

// variant metadata
custom_keyword!(message);
Expand Down Expand Up @@ -56,6 +57,7 @@ impl Spanned for EnumMeta {
pub enum EnumDiscriminantsMeta {
Derive { kw: kw::derive, paths: Vec<Path> },
Name { kw: kw::name, name: Ident },
Vis { kw: kw::vis, vis: Visibility },
Other { path: Path, nested: TokenStream },
}

Expand All @@ -76,6 +78,12 @@ impl Parse for EnumDiscriminantsMeta {
parenthesized!(content in input);
let name = content.parse()?;
Ok(EnumDiscriminantsMeta::Name { kw, name })
} else if input.peek(kw::vis) {
let kw = input.parse()?;
let content;
parenthesized!(content in input);
let vis = content.parse()?;
Ok(EnumDiscriminantsMeta::Vis { kw, vis })
} else {
let path = input.parse()?;
let content;
Expand All @@ -91,6 +99,7 @@ impl Spanned for EnumDiscriminantsMeta {
match self {
EnumDiscriminantsMeta::Derive { kw, .. } => kw.span,
EnumDiscriminantsMeta::Name { kw, .. } => kw.span,
EnumDiscriminantsMeta::Vis { kw, .. } => kw.span,
EnumDiscriminantsMeta::Other { path, .. } => path.span(),
}
}
Expand Down
12 changes: 11 additions & 1 deletion strum_macros/src/helpers/type_props.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use proc_macro2::TokenStream;
use quote::quote;
use std::default::Default;
use syn::{DeriveInput, Ident, Path};
use syn::{DeriveInput, Ident, Path, Visibility};

use super::case_style::CaseStyle;
use super::metadata::{DeriveInputExt, EnumDiscriminantsMeta, EnumMeta};
Expand All @@ -17,6 +17,7 @@ pub struct StrumTypeProperties {
pub discriminant_derives: Vec<Path>,
pub discriminant_name: Option<Ident>,
pub discriminant_others: Vec<TokenStream>,
pub discriminant_vis: Option<Visibility>,
}

impl HasTypeProperties for DeriveInput {
Expand All @@ -41,6 +42,7 @@ impl HasTypeProperties for DeriveInput {
}

let mut name_kw = None;
let mut vis_kw = None;
for meta in discriminants_meta {
match meta {
EnumDiscriminantsMeta::Derive { paths, .. } => {
Expand All @@ -54,6 +56,14 @@ impl HasTypeProperties for DeriveInput {
name_kw = Some(kw);
output.discriminant_name = Some(name);
}
EnumDiscriminantsMeta::Vis { vis, kw } => {
if let Some(fst_kw) = vis_kw {
return Err(occurrence_error(fst_kw, kw, "vis"));
}

vis_kw = Some(kw);
output.discriminant_vis = Some(vis);
}
EnumDiscriminantsMeta::Other { path, nested } => {
output.discriminant_others.push(quote! { #path(#nested) });
}
Expand Down
30 changes: 29 additions & 1 deletion strum_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ pub fn enum_properties(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
/// Variant1 { a: NonDefault },
/// }
///
/// // You can also rename the generated enum using the `#[strum_discriminants(name(OtherName))]` attribute:
/// // You can rename the generated enum using the `#[strum_discriminants(name(OtherName))]` attribute:
/// # #[allow(dead_code)]
/// #[derive(Debug, EnumDiscriminants)]
/// #[strum_discriminants(derive(EnumIter))]
Expand All @@ -607,6 +607,34 @@ pub fn enum_properties(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
/// MyVariants::iter().collect::<Vec<_>>()
/// );
/// ```
///
/// It is also possible to specify the visibility (e.g. `pub`/`pub(crate)`/etc.)
/// of the generated enum. By default, the generated enum inherits the
/// visibility of the parent enum it was generated from.
///
/// ```nocompile
/// use strum_macros::EnumDiscriminants;
///
/// // You can set the visibility of the generated enum using the `#[strum_discriminants(vis(..))]` attribute:
/// mod inner {
/// use strum_macros::EnumDiscriminants;
///
/// # #[allow(dead_code)]
/// #[derive(Debug, EnumDiscriminants)]
/// #[strum_discriminants(vis(pub))]
/// #[strum_discriminants(name(PubDiscriminants))]
/// enum PrivateEnum {
/// Variant0(bool),
/// Variant1 { a: bool },
/// }
/// }
///
/// // test visibility example, `PrivateEnum` should not be accessible here
/// assert_ne!(
/// inner::PubDiscriminants::Variant0,
/// inner::PubDiscriminants::Variant1,
/// );
/// ```
#[cfg_attr(
feature = "verbose-enumdiscriminants-name",
proc_macro_derive(StrumEnumDiscriminants, attributes(strum, strum_discriminants))
Expand Down
3 changes: 2 additions & 1 deletion strum_macros/src/macros/enum_discriminants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn enum_discriminants_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
);

let discriminants_name = type_properties.discriminant_name.unwrap_or(default_name);
let discriminants_vis = type_properties.discriminant_vis.unwrap_or_else(|| vis.clone());

// Pass through all other attributes
let pass_though_attributes = type_properties.discriminant_others;
Expand Down Expand Up @@ -127,7 +128,7 @@ pub fn enum_discriminants_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
/// Auto-generated discriminant enum variants
#derives
#(#[ #pass_though_attributes ])*
#vis enum #discriminants_name {
#discriminants_vis enum #discriminants_name {
#(#discriminants),*
}

Expand Down
1 change: 1 addition & 0 deletions strum_tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ fn main() {
// Check if version of rustc is >= 1.34
if let Some(true) = version_check::is_min_version("1.34.0") {
println!("cargo:rustc-cfg=try_from");
println!("cargo:rustc-cfg=bare_pub");
}
}
42 changes: 42 additions & 0 deletions strum_tests/tests/enum_discriminants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,45 @@ fn filter_variant_attributes_pass_through() {
VariantFilterAttrDiscs::from_str("dark_black").unwrap()
);
}

#[cfg(bare_pub)]
#[test]
linclelinkpart5 marked this conversation as resolved.
Show resolved Hide resolved
fn override_visibility() {
mod private {
use super::*;

#[allow(dead_code)]
#[derive(EnumDiscriminants)]
#[strum_discriminants(name(PubDiscriminants), vis(pub))]
enum PrivateEnum {
VariantA(bool),
VariantB(bool),
}
}

assert_ne!(
private::PubDiscriminants::VariantA,
private::PubDiscriminants::VariantB,
);
}

#[cfg(not(bare_pub))]
#[test]
fn override_visibility() {
mod private {
use super::*;

#[allow(dead_code)]
#[derive(EnumDiscriminants)]
#[strum_discriminants(name(PubDiscriminants), vis(r#pub))]
enum PrivateEnum {
VariantA(bool),
VariantB(bool),
}
}

assert_ne!(
private::PubDiscriminants::VariantA,
private::PubDiscriminants::VariantB,
);
}