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