visibility/
lib.rs

1#![forbid(unsafe_code)]
2#![allow(nonstandard_style, unused_imports)]
3#![cfg_attr(feature = "nightly",
4    cfg_attr(all(), doc = include_str!("../README.md")),
5)]
6
7extern crate proc_macro;
8
9use ::proc_macro::TokenStream;
10use ::proc_macro2::{Span, TokenStream as TokenStream2};
11use ::quote::{
12    quote,
13    quote_spanned,
14    ToTokens,
15};
16use ::syn::{*,
17    parse::Parse,
18    Result,
19};
20
21/// **Override**s the visibility of the annotated item with the one given to
22/// this attribute:
23///
24/// ## Example
25///
26/// ```rust
27/// mod module {
28///     #[visibility::make(pub)]
29///     fn foo () {}
30/// }
31///
32/// module::foo();
33/// ```
34///
35/// ## To be used in conjunction with `#[cfg_attr]`
36///
37/// That's where this attribute really shines: it is not possible to
38/// conditionally modify the visibility of an item, but it is possible to
39/// conditionally apply an attribute. If the attribute then modifies the
40/// visibility of the decorated item, we have achieved our goal:
41///
42/// ```rust
43/// mod module {
44///     #[cfg_attr(all(/* feature = "integration-tests" */),
45///         visibility::make(pub),
46///     )]
47///     fn foo () {}
48/// }
49///
50/// module::foo();
51/// ```
52#[proc_macro_attribute] pub
53fn make (attrs: TokenStream, input: TokenStream)
54  -> TokenStream
55{
56    let visibility: Visibility = parse_macro_input!(attrs);
57    let mut input: Item = parse_macro_input!(input);
58
59    match input {
60        | Item::Const(ItemConst { ref mut vis, .. }) => *vis = visibility,
61        | Item::Enum(ItemEnum { ref mut vis, .. }) => *vis = visibility,
62        | Item::ExternCrate(ItemExternCrate { ref mut vis, .. }) => *vis = visibility,
63        | Item::Fn(ItemFn { ref mut vis, .. }) => *vis = visibility,
64        // | Item::ForeignMod(ItemForeignMod { ref mut vis, .. }) => *vis = visibility,
65        // | Item::Impl(ItemImpl { ref mut vis, .. }) => *vis = visibility,
66        // | Item::Macro(ItemMacro { ref mut vis, .. }) => *vis = visibility,
67        | Item::Mod(ItemMod { ref mut vis, .. }) => *vis = visibility,
68        | Item::Static(ItemStatic { ref mut vis, .. }) => *vis = visibility,
69        | Item::Struct(ItemStruct { ref mut vis, .. }) => *vis = visibility,
70        | Item::Trait(ItemTrait { ref mut vis, .. }) => *vis = visibility,
71        | Item::TraitAlias(ItemTraitAlias { ref mut vis, .. }) => *vis = visibility,
72        | Item::Type(ItemType { ref mut vis, .. }) => *vis = visibility,
73        | Item::Union(ItemUnion { ref mut vis, .. }) => *vis = visibility,
74        | Item::Use(ItemUse { ref mut vis, .. }) => *vis = visibility,
75        // | Item::Verbatim(TokenStream { ref mut vis, .. }) => *vis = visibility,
76
77        | _ => return Error::new_spanned(
78            &input,
79            "Cannot override the `#[visibility]` of this item",
80        ).to_compile_error().into(),
81    }
82
83    input.into_token_stream().into()
84}