scopes_macros/
lib.rs

1#![warn(missing_docs)]
2//! Macros for [`scopes-rs`](https://github.com/aripot007/scopes-rs)
3//!
4//! This crate is re-exported by `scopes-rs`, and its documentation should be
5//! browsed from the `scopes-rs` crate.
6//!  
7extern crate proc_macro2;
8
9use darling::FromDeriveInput;
10use proc_macro::TokenStream;
11
12use crate::scope::{Scope, opts::ScopeOpts, scope_impl::derive_into_scope_impl};
13
14
15#[cfg(feature = "hierarchy")]
16mod hierarchy;
17
18mod scope;
19
20/// ## Optional `#[scope(...)]` attributes for the enum
21/// 
22/// - `separator = "..."`: Change the separator between scope labels. Defaults to `"."`
23/// - `prefix = "..."`: Add a prefix to every generated scope name. Default is an empty prefix
24/// - `hierarchy = bool`: Enable or disable generation of the `Hierarchized` trait. Requires the `hierarchy`
25///     feature. Defaults to `true`.
26/// - `scope_name_getter = bool`: Implement the `scope_name()` function to get the scope name from a variant (defaults to true)
27/// 
28/// ## Optional `#[scope(...)]` attributes for enum variants
29/// 
30/// - `rename = "..."`: Use a specific name instead of inferring it from the variant name
31/// - `include = scope | [scope1, ...]`: Include other scopes in the hierarchy. See below for more details.
32///     requires the `hierarchy` feature
33/// 
34/// ### Hierarchy customization
35/// 
36/// The generated scopes hierarchy can be customized with the `#[scope(include = ...)]` attribute.
37/// 
38/// The attributes takes a scope variant or a list of scope variants that should be included in the scope :
39/// 
40/// 
41/// ```ignore
42/// use scopes_rs::{
43///     derive::Scope,
44///     hierarchy::Hierarchized,
45/// };
46/// 
47/// #[derive(Clone, Debug, PartialEq, Scope)]
48/// enum MyScope {
49/// 
50///     Foo,
51///     #[scope(include = FooBarReadonly)]
52///     FooReadonly,
53/// 
54///     FooBar,
55///     FooBarReadonly,
56///     
57///     #[scope(include = [FooReadonly, BarReadonly])]
58///     Readonly,
59///     
60///     Bar,
61///     BarReadonly,
62/// }
63/// 
64/// assert!(MyScope::Readonly.includes(&MyScope::BarReadonly));
65/// assert!(MyScope::Readonly.includes(&MyScope::FooReadonly));
66/// 
67/// // Inclusion is transitive, so Readonly also includes FooBarReadonly 
68/// // since FooReadonly includes it
69/// assert!(MyScope::Readonly.includes(&MyScope::FooBarReadonly))
70/// ```
71#[proc_macro_derive(Scope, attributes(scope))]
72pub fn derive_into_scope(item: TokenStream) -> TokenStream {
73    
74    let input = syn::parse_macro_input!(item as syn::DeriveInput);
75
76    let opts = match ScopeOpts::from_derive_input(&input) {
77        Ok(opts) => opts,
78        Err(err) => {
79            return err.write_errors().into()
80        },
81    };
82    
83    derive_into_scope_impl(&opts)
84}