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}