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}