diff options
author | HampusM <hampus@hampusmat.com> | 2022-07-24 15:58:30 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-07-24 15:58:30 +0200 |
commit | 5335cdad99a6d566ea6e83f97012c7954ba93c45 (patch) | |
tree | b4c91634b34f6d3858d6dd210afb609d9a1f76d7 /macros | |
parent | 5ea16d1e5bf716831bc8c54c5c4c86229d7e0463 (diff) |
feat: add support for generics
Diffstat (limited to 'macros')
-rw-r--r-- | macros/src/injectable_impl.rs | 15 | ||||
-rw-r--r-- | macros/src/lib.rs | 25 |
2 files changed, 30 insertions, 10 deletions
diff --git a/macros/src/injectable_impl.rs b/macros/src/injectable_impl.rs index 8bb6c7a..822a432 100644 --- a/macros/src/injectable_impl.rs +++ b/macros/src/injectable_impl.rs @@ -1,5 +1,6 @@ use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; +use syn::Generics; use syn::{ parse_str, punctuated::Punctuated, token::Comma, ExprMethodCall, FnArg, GenericArgument, Ident, ImplItem, ImplItemMethod, ItemImpl, Path, PathArguments, @@ -12,6 +13,7 @@ pub struct InjectableImpl { pub dependency_types: Vec<Type>, pub self_type: Type, + pub generics: Generics, pub original_impl: ItemImpl, } @@ -25,6 +27,7 @@ impl Parse for InjectableImpl Ok(dependency_types) => Ok(Self { dependency_types, self_type: impl_parsed_input.self_ty.as_ref().clone(), + generics: impl_parsed_input.generics.clone(), original_impl: impl_parsed_input, }), Err(error_msg) => Err(input.error(error_msg)), @@ -39,17 +42,21 @@ impl InjectableImpl { pub fn expand(&self) -> proc_macro2::TokenStream { - let original_impl = &self.original_impl; - let self_type = &self.self_type; + let Self { + dependency_types, + self_type, + generics, + original_impl, + } = self; let di_container_var: Ident = parse_str(DI_CONTAINER_VAR_NAME).unwrap(); - let get_dependencies = Self::_create_get_dependencies(&self.dependency_types); + let get_dependencies = Self::_create_get_dependencies(dependency_types); quote! { #original_impl - impl syrette::interfaces::injectable::Injectable for #self_type { + impl #generics syrette::interfaces::injectable::Injectable for #self_type { fn resolve( #di_container_var: &syrette::DIContainer ) -> syrette::libs::error_stack::Result< diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 73fb2dc..d65df68 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -19,27 +19,40 @@ use libs::intertrait_macros::gen_caster::generate_caster; /// Makes a struct injectable. Thereby usable with `DIContainer`. /// /// # Arguments -/// * A interface trait the struct implements. +/// * (Optional) A interface trait the struct implements. /// /// # Panics /// If the attributed item is not a impl. +/// +/// # Important +/// If the interface trait argument is excluded, you should either manually +/// declare the interface with the `declare_interface` macro or use +/// the `di_container_bind` macro to create a DI container binding. #[proc_macro_attribute] pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenStream { - let InjectableMacroArgs { - interface: interface_type_path, - } = parse_macro_input!(args_stream); + let should_declare_interface = !args_stream.is_empty(); let injectable_impl: InjectableImpl = parse(impl_stream).unwrap(); let expanded_injectable_impl = injectable_impl.expand(); - let self_type = &injectable_impl.self_type; + let maybe_decl_interface = if should_declare_interface { + let InjectableMacroArgs { interface } = parse_macro_input!(args_stream); + + let self_type = &injectable_impl.self_type; + + quote! { + syrette::declare_interface!(#self_type -> #interface); + } + } else { + quote! {} + }; quote! { #expanded_injectable_impl - syrette::declare_interface!(#self_type -> #interface_type_path); + #maybe_decl_interface } .into() } |