1
0
mirror of https://github.com/danog/strum.git synced 2024-11-30 04:28:59 +01:00

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

* Adding vis to EnumDiscriminants (#137)

* Improved doctest example names (#137)

* Fixing incorrect occurrence_error attr string

* Using r#pub on doctest

* Adding tests for discriminant visibility, and rustc-cfg for bare "pub"

* Doing local import with "self::"

* Back to having tests pass on latest stable

* Moved sample doctest with vis example to separate nocompile block
This commit is contained in:
Mark LeMoine 2020-11-15 20:13:50 -08:00 committed by GitHub
parent 90047fee86
commit ddb9c2682e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 4 deletions

View File

@ -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;
@ -18,6 +18,7 @@ pub mod kw {
// enum discriminant metadata
custom_keyword!(derive);
custom_keyword!(name);
custom_keyword!(vis);
// variant metadata
custom_keyword!(message);
@ -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 },
}
@ -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;
@ -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(),
}
}

View File

@ -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};
@ -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 {
@ -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, .. } => {
@ -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) });
}

View File

@ -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))]
@ -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))

View File

@ -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;
@ -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),*
}

View File

@ -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");
}
}

View File

@ -215,3 +215,45 @@ fn filter_variant_attributes_pass_through() {
VariantFilterAttrDiscs::from_str("dark_black").unwrap()
);
}
#[cfg(bare_pub)]
#[test]
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,
);
}