diff options
author | HampusM <hampus@hampusmat.com> | 2023-03-18 17:14:42 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-03-18 17:15:30 +0100 |
commit | c48271aef7e6b0819c497f302127c161845a83d7 (patch) | |
tree | a18d7b5fc8e017b4b7e0917a55534b28a01fe57d /src | |
parent | 2ca8017deebe7bfe5aac368aead777a2c4910ca2 (diff) |
refactor: rewrite the mock macro as a procedural macro
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 229 |
1 files changed, 3 insertions, 226 deletions
@@ -1,196 +1,10 @@ -#[macro_export] -macro_rules! mock { - ( - $mock: ident; +#![deny(clippy::all, clippy::pedantic)] - impl $mocked_trait: ident for $mocked_trait_target: ident { - $( - fn $func: ident$(< - $($type_param: tt$(: ($($type_param_bound: tt +)+))?),* - >)?( - self: ($($self_type: tt)+), - $($func_param: ident: $func_param_type: ty),* - )$( -> $return_type: ty)? - $(where $( - $where_param: ident: $first_where_param_bound: tt $(+ $where_param_bound: tt)* - ),*)?; - )* - } - ) => { - $crate::__private::paste! { - mod [<__ $mock>] { - use super::*; - - pub struct $mock { - $( - [<$func _expectations>]: std::collections::HashMap< - Vec<$crate::__private::type_id::TypeID>, - [<$mock Expectation _ $func>]$(<$($crate::__to_unit!($type_param)),*>)? - >, - )* - } - - impl $mock - { - pub fn new() -> Self - { - Self { - $( - [<$func _expectations>]: std::collections::HashMap::new() - ),* - } - } - - $( - #[allow(unused)] - pub(crate) fn [<expect_ $func>]$(< - $($type_param$(: $($type_param_bound +)*)?),* - >)?(&mut self) - -> &mut [<$mock Expectation _ $func>]$(<$($type_param),*>)? - $(where $( - $where_param: $first_where_param_bound $(+ $where_param_bound)* - ),*)? - { - let ids = vec![ - $($($crate::__private::type_id::TypeID::of::<$type_param>()),*)? - ]; - - let expectation = - [<$mock Expectation _ $func>]$(::<$($type_param),*>)?::new() - .strip_type_params(); - - self.[<$func _expectations>].insert(ids.clone(), expectation); - - self.[<$func _expectations>] - .get_mut(&ids) - .unwrap() - .with_type_params_mut() - } - )* - } - - impl $mocked_trait for $mock { - $( - fn $func$(<$($type_param$(: $($type_param_bound +)+)?),*>)?( - self: $($self_type)+, - $($func_param: $func_param_type),* - )$( -> $return_type)? - $(where $( - $where_param: $first_where_param_bound $(+ $where_param_bound)* - ),*)? - { - let ids = vec![ - $($($crate::__private::type_id::TypeID::of::<$type_param>()),*)? - ]; - - let expectation = self - .[<$func _expectations>] - .get(&ids) - .expect(concat!( - "No expectation found for function ", - stringify!($func) - )) - .with_type_params$(::<$($type_param),*>)?(); - - let Some(returning) = &expectation.returning else { - panic!(concat!( - "Expectation for function", - stringify!($func), - " is missing a function to call") - ); - }; - - returning(self, $($func_param),*) - } - )* - } - - $( - #[allow(non_camel_case_types, non_snake_case)] - pub struct [<$mock Expectation _ $func>]$(<$($type_param),*>)? { - returning: Option< - fn( - $crate::__replace_ref_type!($($self_type)*, $mock), - $($func_param_type),* - )$( -> $return_type)?>, - - $( - $([<$type_param _phantom>]: std::marker::PhantomData<$type_param>,)* - )? - } - - impl$(<$($type_param),*>)? [<$mock Expectation _ $func>]$(< - $($type_param),* - >)? { - #[allow(unused)] - fn new() -> Self { - Self { - returning: None, - $( - $([<$type_param _phantom>]: std::marker::PhantomData,)* - )? - } - } - - #[allow(unused)] - pub fn returning( - &mut self, - func: fn( - $crate::__replace_ref_type!($($self_type)*, $mock), - $($func_param_type),* - )$( -> $return_type)? - ) -> &mut Self - { - self.returning = Some(func); - - self - } - - #[allow(unused)] - fn strip_type_params( - self, - ) -> [<$mock Expectation _ $func>]$(<$($crate::__to_unit!($type_param)),*>)? - { - $crate::__if_empty_else!(($($($type_param)*)?); { - // No type parameters are present - self - }, { - // Type parameters are present - unsafe { std::mem::transmute(self) } - }) - - } - } - - impl [<$mock Expectation _ $func>]$(<$($crate::__to_unit!($type_param)),*>)? { - fn with_type_params$(<$($type_param),*>)?( - &self, - ) -> &[<$mock Expectation _ $func>]$(<$($type_param),*>)? - { - unsafe { &*(self as *const Self).cast() } - } - - #[allow(unused)] - fn with_type_params_mut$(<$($type_param),*>)?( - &mut self, - ) -> &mut [<$mock Expectation _ $func>]$(<$($type_param),*>)? - { - unsafe { &mut *(self as *mut Self).cast() } - } - } - )* - } - - use [<__ $mock>]::$mock; - } - }; -} +pub use ridicule_macros::mock; #[doc(hidden)] pub mod __private { - pub use paste::paste; - pub mod type_id { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -202,6 +16,7 @@ pub mod __private impl TypeID { #[inline] + #[must_use] pub fn of<T>() -> Self { Self { @@ -210,42 +25,4 @@ pub mod __private } } } - - #[macro_export] - #[doc(hidden)] - macro_rules! __to_unit { - ($anything: tt) => { - () - }; - } - - #[macro_export] - #[doc(hidden)] - macro_rules! __replace_ref_type { - (&$old_type: tt, $new_type: tt) => { - &$new_type - }; - - (&mut $old_type: tt, $new_type: tt) => { - &mut $new_type - }; - } - - #[macro_export] - #[doc(hidden)] - macro_rules! __if_empty_else { - (($($input: tt)*); $if_empty: block, $else: block) => { - $crate::__if_empty_else!(@($($input)*); $if_empty, $else) - }; - - // Empty - (@(); $if_empty: block, $else: block) => { - $if_empty - }; - - // Not empty - (@($($input: tt)+); $if_empty: block, $else: block) => { - $else - }; - } } |