From c501a5cc770f632eba1529de09bd3ae2d7958de6 Mon Sep 17 00:00:00 2001 From: HampusM Date: Fri, 22 Dec 2023 22:33:09 +0100 Subject: refactor: mock Dependency struct impl instead of IDependency --- Cargo.lock | 1 + macros/Cargo.toml | 1 + macros/src/injectable/dependency.rs | 35 ++++++++------------ macros/src/injectable/implementation.rs | 57 +++++++++++++++++---------------- macros/src/lib.rs | 4 +-- macros/src/util/mod.rs | 40 ++++++++++++++++++++++- 6 files changed, 85 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e8b58c..64e414a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -519,6 +519,7 @@ version = "0.5.1" dependencies = [ "mockall", "once_cell", + "paste", "pretty_assertions", "proc-macro-error", "proc-macro2", diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 12f3f0b..3e2d469 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -28,6 +28,7 @@ uuid = { version = "0.8", features = ["v4"] } once_cell = "1.13.1" thiserror = "1.0.37" proc-macro-error = "1.0.4" +paste = "1.0.8" [target.'cfg(syrette_macros_logging)'.dependencies] tracing = "0.1.37" diff --git a/macros/src/injectable/dependency.rs b/macros/src/injectable/dependency.rs index 8e22f21..30c156f 100644 --- a/macros/src/injectable/dependency.rs +++ b/macros/src/injectable/dependency.rs @@ -6,23 +6,6 @@ use crate::injectable::named_attr_input::NamedAttrInput; use crate::util::error::diagnostic_error_enum; use crate::util::syn_path::SynPathExt; -/// Interface for a dependency of a `Injectable`. -#[cfg_attr(test, mockall::automock)] -pub trait IDependency: Sized -{ - /// Build a new `Dependency` from a argument in a constructor method. - fn build(ctor_method_arg: &FnArg) -> Result; - - /// Returns the interface type. - fn get_interface(&self) -> &Type; - - /// Returns the pointer type identity. - fn get_ptr(&self) -> &Ident; - - /// Returns optional name of the dependency. - fn get_name(&self) -> &Option; -} - /// Representation of a dependency of a injectable type. /// /// Found as a argument in the constructor method of a `Injectable`. @@ -34,9 +17,11 @@ pub struct Dependency name: Option, } -impl IDependency for Dependency +#[cfg_attr(test, mockall::automock)] +impl Dependency { - fn build(ctor_method_arg: &FnArg) -> Result + /// Build a new `Dependency` from a argument in a constructor method. + pub fn build(ctor_method_arg: &FnArg) -> Result { let typed_ctor_method_arg = match ctor_method_arg { FnArg::Typed(typed_arg) => Ok(typed_arg), @@ -116,17 +101,23 @@ impl IDependency for Dependency }) } - fn get_interface(&self) -> &Type + /// Returns the dependency's interface type. + #[allow(dead_code)] // Mock function is never used + pub fn get_interface(&self) -> &Type { &self.interface } - fn get_ptr(&self) -> &Ident + /// Returns the dependency's pointer type name. + #[allow(dead_code)] // Mock function is never used + pub fn get_ptr(&self) -> &Ident { &self.ptr } - fn get_name(&self) -> &Option + /// Returns the dependency's name. + #[allow(dead_code)] // Mock function is never used + pub fn get_name(&self) -> &Option { &self.name } diff --git a/macros/src/injectable/implementation.rs b/macros/src/injectable/implementation.rs index a98d1ce..a67b4a3 100644 --- a/macros/src/injectable/implementation.rs +++ b/macros/src/injectable/implementation.rs @@ -16,7 +16,7 @@ use syn::{ Type, }; -use crate::injectable::dependency::{DependencyError, IDependency}; +use crate::injectable::dependency::DependencyError; use crate::util::error::diagnostic_error_enum; use crate::util::item_impl::find_impl_method_by_name_mut; use crate::util::string::camelcase_to_snakecase; @@ -28,19 +28,22 @@ use crate::util::syn_ext::{ MethodTurbofishExt, }; use crate::util::syn_path::{syn_path, SynPathExt}; +use crate::util::use_double; + +use_double!(crate::injectable::dependency::Dependency); const DI_CONTAINER_VAR_NAME: &str = "di_container"; const DEPENDENCY_HISTORY_VAR_NAME: &str = "dependency_history"; -pub struct InjectableImpl +pub struct InjectableImpl { - dependencies: Vec, + dependencies: Vec, original_impl: ItemImpl, constructor_method: ImplItemMethod, } -impl InjectableImpl +impl InjectableImpl { #[cfg(not(tarpaulin_include))] pub fn new( @@ -334,7 +337,7 @@ impl InjectableImpl } fn create_get_dep_method_calls( - dependencies: &[Dep], + dependencies: &[Dependency], is_async: bool, di_container_var: &Ident, dependency_history_var: &Ident, @@ -353,7 +356,7 @@ impl InjectableImpl .collect() } - fn create_binding_options(dependency: &Dep) -> Expr + fn create_binding_options(dependency: &Dependency) -> Expr { let binding_options_new = Expr::Call(ExprCall::new( Expr::Path(ExprPath::new(syn_path!( @@ -373,7 +376,7 @@ impl InjectableImpl } fn create_single_get_dep_method_call( - dependency: &Dep, + dependency: &Dependency, is_async: bool, di_container_var: &Ident, dependency_history_var: &Ident, @@ -432,12 +435,12 @@ impl InjectableImpl fn build_dependencies( ctor_method: &ImplItemMethod, - ) -> Result, DependencyError> + ) -> Result, DependencyError> { let ctor_method_args = &ctor_method.sig.inputs; let dependencies_result: Result, _> = - ctor_method_args.iter().map(Dep::build).collect(); + ctor_method_args.iter().map(Dependency::build).collect(); let deps = dependencies_result?; @@ -582,7 +585,7 @@ mod tests }; use super::*; - use crate::injectable::dependency::MockIDependency; + use crate::injectable::dependency::MockDependency; use crate::injectable::named_attr_input::NamedAttrInput; use crate::test_utils::{ create_path, @@ -650,14 +653,14 @@ mod tests let _lock = get_lock(&TEST_MUTEX); - let build_context = MockIDependency::build_context(); + let build_context = MockDependency::build_context(); build_context .expect() - .returning(|_| Ok(MockIDependency::new())); + .returning(|_| Ok(MockDependency::new())); - let dependencies = InjectableImpl::::build_dependencies(&method) - .expect("Expected Ok"); + let dependencies = + InjectableImpl::build_dependencies(&method).expect("Expected Ok"); assert_eq!(dependencies.len(), 2); } @@ -719,15 +722,15 @@ mod tests let _lock = get_lock(&TEST_MUTEX); - let build_context = MockIDependency::build_context(); + let build_context = MockDependency::build_context(); build_context .expect() - .returning(|_| Ok(MockIDependency::new())) + .returning(|_| Ok(MockDependency::new())) .times(2); - let dependencies = InjectableImpl::::build_dependencies(&method) - .expect("Expected Ok"); + let dependencies = + InjectableImpl::build_dependencies(&method).expect("Expected Ok"); assert_eq!(dependencies.len(), 2); } @@ -804,7 +807,7 @@ mod tests }, }; - InjectableImpl::::remove_method_argument_attrs(&mut method); + InjectableImpl::remove_method_argument_attrs(&mut method); assert_eq!( method.sig.inputs.first().unwrap().clone(), @@ -830,7 +833,7 @@ mod tests #[test] fn can_create_single_get_dep_method_call() { - let mut mock_dependency = MockIDependency::new(); + let mut mock_dependency = MockDependency::new(); mock_dependency .expect_get_interface() @@ -848,7 +851,7 @@ mod tests let di_container_var_ident = format_ident!("{}", DI_CONTAINER_VAR_NAME); let dep_history_var_ident = format_ident!("{}", DEPENDENCY_HISTORY_VAR_NAME); - let output = InjectableImpl::::create_single_get_dep_method_call( + let output = InjectableImpl::create_single_get_dep_method_call( &mock_dependency, false, &format_ident!("{}", DI_CONTAINER_VAR_NAME), @@ -880,7 +883,7 @@ mod tests #[test] fn can_create_single_get_dep_method_call_with_name() { - let mut mock_dependency = MockIDependency::new(); + let mut mock_dependency = MockDependency::new(); mock_dependency .expect_get_interface() @@ -900,7 +903,7 @@ mod tests let di_container_var_ident = format_ident!("{}", DI_CONTAINER_VAR_NAME); let dep_history_var_ident = format_ident!("{}", DEPENDENCY_HISTORY_VAR_NAME); - let output = InjectableImpl::::create_single_get_dep_method_call( + let output = InjectableImpl::create_single_get_dep_method_call( &mock_dependency, false, &format_ident!("{}", DI_CONTAINER_VAR_NAME), @@ -932,7 +935,7 @@ mod tests #[test] fn can_create_single_get_dep_method_call_async() { - let mut mock_dependency = MockIDependency::new(); + let mut mock_dependency = MockDependency::new(); mock_dependency .expect_get_interface() @@ -950,7 +953,7 @@ mod tests let di_container_var_ident = format_ident!("{}", DI_CONTAINER_VAR_NAME); let dep_history_var_ident = format_ident!("{}", DEPENDENCY_HISTORY_VAR_NAME); - let output = InjectableImpl::::create_single_get_dep_method_call( + let output = InjectableImpl::create_single_get_dep_method_call( &mock_dependency, true, &format_ident!("{}", DI_CONTAINER_VAR_NAME), @@ -983,7 +986,7 @@ mod tests #[test] fn can_create_single_get_dep_method_call_async_with_name() { - let mut mock_dependency = MockIDependency::new(); + let mut mock_dependency = MockDependency::new(); mock_dependency .expect_get_interface() @@ -1003,7 +1006,7 @@ mod tests let di_container_var_ident = format_ident!("{}", DI_CONTAINER_VAR_NAME); let dep_history_var_ident = format_ident!("{}", DEPENDENCY_HISTORY_VAR_NAME); - let output = InjectableImpl::::create_single_get_dep_method_call( + let output = InjectableImpl::create_single_get_dep_method_call( &mock_dependency, true, &format_ident!("{}", DI_CONTAINER_VAR_NAME), diff --git a/macros/src/lib.rs b/macros/src/lib.rs index e55e23f..b9b6ea5 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -23,7 +23,6 @@ use syn::{ use crate::caster::generate_caster; use crate::declare_interface_args::DeclareInterfaceArgs; -use crate::injectable::dependency::Dependency; use crate::injectable::dummy::expand_dummy_blocking_impl; use crate::injectable::implementation::{InjectableImpl, InjectableImplError}; use crate::injectable::macro_args::InjectableMacroArgs; @@ -255,8 +254,7 @@ pub fn injectable(args_stream: TokenStream, input_stream: TokenStream) -> TokenS ); } - let injectable_impl = - InjectableImpl::::new(item_impl, &constructor).unwrap_or_abort(); + let injectable_impl = InjectableImpl::new(item_impl, &constructor).unwrap_or_abort(); injectable_impl.validate(is_async).unwrap_or_abort(); diff --git a/macros/src/util/mod.rs b/macros/src/util/mod.rs index 7ab2185..3557896 100644 --- a/macros/src/util/mod.rs +++ b/macros/src/util/mod.rs @@ -26,4 +26,42 @@ macro_rules! or { }; } -pub(crate) use {or, to_option}; +/// Imports the specified item, prepending 'Mock' to the item identifier if the `test` +/// configuration option is set. +/// +/// # Examples +/// ```ignore +/// use_double!(crate::dependency_history::DependencyHistory); +/// ``` +///
+/// +/// Expands to the following when `cfg(not(test))` +/// ```ignore +/// use crate::dependency_history::DependencyHistory; +/// ``` +///
+/// +/// Expands to the following when `cfg(test)` +/// ```ignore +/// use crate::dependency_history::MockDependencyHistory as DependencyHistory; +/// ``` +macro_rules! use_double { + ($([$($part: ident),*])? $item_path_part: ident :: $($next_part: tt)+) => { + use_double!( + [$($($part,)*)? $item_path_part] + $($next_part)+ + ); + }; + + ([$($part: ident),*] $item_path_part: ident) => { + #[cfg(not(test))] + use $($part::)* $item_path_part; + + ::paste::paste! { + #[cfg(test)] + use $($part::)* [] as $item_path_part; + } + }; +} + +pub(crate) use {or, to_option, use_double}; -- cgit v1.2.3-18-g5258