nject_macro/
lib.rs

1#![allow(clippy::needless_doctest_main)]
2#![doc = include_str!("../README.md")]
3mod core;
4mod inject;
5mod injectable;
6mod module;
7mod provider;
8use inject::handle_inject;
9use injectable::handle_injectable;
10use module::handle_module;
11use proc_macro::TokenStream;
12use provider::handle_provider;
13
14/// For internal purposes only. Should not be used.
15#[proc_macro_derive(InjectableHelperAttr, attributes(inject))]
16pub fn injectable_helper_attr(_item: TokenStream) -> TokenStream {
17    TokenStream::new()
18}
19
20/// For internal purposes only. Should not be used.
21#[proc_macro_derive(ModuleHelperAttr, attributes(export))]
22pub fn module_helper_attr(_item: TokenStream) -> TokenStream {
23    TokenStream::new()
24}
25
26/// For internal purposes only. Should not be used.
27#[proc_macro_derive(ProviderHelperAttr, attributes(import, provide, scope))]
28pub fn provider_helper_attr(_item: TokenStream) -> TokenStream {
29    TokenStream::new()
30}
31
32/// For internal purposes only. Should not be used.
33#[proc_macro_derive(ScopeHelperAttr, attributes(arg))]
34pub fn scope_helper_attr(_item: TokenStream) -> TokenStream {
35    TokenStream::new()
36}
37
38/// Mark a struct as injectable.
39/// ```rust
40/// use nject::{injectable, provider};
41///
42/// #[injectable]
43/// struct Facade;
44///
45/// #[provider]
46/// struct Provider;
47///
48/// let facade: Facade = Provider.provide();
49/// ```
50#[proc_macro_attribute]
51pub fn injectable(_attr: TokenStream, item: TokenStream) -> TokenStream {
52    handle_injectable(item).unwrap_or_else(|e| e.to_compile_error().into())
53}
54
55/// Use the given value to inject.
56/// ```rust
57/// use nject::{inject, injectable, provider};
58///
59/// #[inject(Self { value: 42 })]
60/// struct DepOne {
61///     value: i32,
62/// }
63///
64/// #[inject(|injectable_dep: DepOne| Self(12, injectable_dep))]
65/// struct DepTwo(i32, DepOne);
66///
67/// #[injectable]
68/// struct Facade(DepOne, DepTwo, #[inject(123)] i32);
69///
70/// #[provider]
71/// struct Provider;
72///
73/// let facade: Facade = Provider.provide();
74/// ```
75#[proc_macro_attribute]
76pub fn inject(attr: TokenStream, item: TokenStream) -> TokenStream {
77    handle_inject(item, attr).unwrap_or_else(|e| e.to_compile_error().into())
78}
79
80/// Provide a value for a specific type.
81/// ```rust
82/// use nject::{injectable, provider};
83///
84/// struct Dependency {
85///     value: i32,
86/// }
87///
88/// struct SharedDependency {
89///     value: i32,
90/// }
91///
92/// #[injectable]
93/// struct Facade<'a>(Dependency, &'a SharedDependency);
94///
95/// #[provider]
96/// #[provide(Dependency, Dependency { value: 123 })]
97/// struct Provider {
98///     #[provide]
99///     shared: SharedDependency
100/// }
101///
102/// let provider = Provider { shared: SharedDependency { value: 456 } };
103/// let dependency: Dependency = provider.provide();
104/// let facade: Facade = provider.provide();
105/// ```
106#[proc_macro_attribute]
107pub fn provider(_attr: TokenStream, item: TokenStream) -> TokenStream {
108    handle_provider(item).unwrap_or_else(|e| e.to_compile_error().into())
109}
110
111/// Declare a module to export internal types.
112/// ```rust
113/// use nject::{injectable, provider};
114///
115/// mod sub {
116///     use nject::{injectable, module};
117///     use std::rc::Rc;
118///
119///     #[injectable]
120///     struct InternalType(#[inject(123)] i32); // Not visible outside of module.
121///
122///     #[injectable]
123///     pub struct Facade<'a> {
124///         hidden: &'a InternalType,
125///         public: Rc<i32>,
126///     }
127///
128///     #[injectable]
129///     // The absolute public path to access the module.
130///     // If no path is given, the struct name will be used and must be unique across all modules.
131///     // Keywords like `crate` and `Self` will be substituted accordingly.
132///     #[module(crate::sub::Self)]
133///     // Public type exports must be made on the struct (not the fields).
134///     // To prevent name collisions, use absolute paths in types.
135///     #[export(std::rc::Rc<i32>, self.public.clone())]
136///     pub struct Module {
137///         #[export] // Fields exports are for internal types.
138///         hidden: InternalType,
139///         #[inject(Rc::new(456))]
140///         public: Rc<i32>,
141///     }
142/// }
143///
144/// #[injectable]
145/// #[provider]
146/// struct Provider {
147///     #[import]
148///     // To import module public exports, use the absolute path given in its definition.
149///     sub_mod: crate::sub::Module,
150/// }
151///
152/// #[provider]
153/// struct InitProvider;
154///
155/// fn main() {
156///     let provider = InitProvider.provide::<Provider>();
157///     let facade = provider.provide::<sub::Facade>();
158/// }
159/// ```
160#[proc_macro_attribute]
161pub fn module(attr: TokenStream, item: TokenStream) -> TokenStream {
162    handle_module(attr, item).unwrap_or_else(|e| e.to_compile_error().into())
163}