diff options
author | HampusM <hampus@hampusmat.com> | 2023-03-26 17:39:27 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-03-26 17:39:27 +0200 |
commit | 1628732d6514670fe2108e5063e9d5ba7166ad94 (patch) | |
tree | 4e54f68ed3869b8b50adceba6e8c95b3db53d41e | |
parent | 7f9294869afd07e096e73a45e6a101b8970a0e6e (diff) |
fix: replace Self in generics
-rw-r--r-- | examples/automock.rs | 12 | ||||
-rw-r--r-- | macros/src/lib.rs | 116 |
2 files changed, 116 insertions, 12 deletions
diff --git a/examples/automock.rs b/examples/automock.rs index c8725ce..a597678 100644 --- a/examples/automock.rs +++ b/examples/automock.rs @@ -3,14 +3,22 @@ use ridicule::predicate::{always, eq}; use crate::cool_trais::MockFoo; +pub trait DoStuff<Thing> {} + +impl<TFoo: Foo> DoStuff<TFoo> for f32 {} + mod cool_trais { use ridicule::automock; + use crate::DoStuff; + #[automock] - pub trait Foo + pub trait Foo: Sized { - fn bar<Something>(&self, num: u128, text: &str) -> Something; + fn bar<Something>(&self, num: u128, text: &str) -> Something + where + Something: DoStuff<Self>; } } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index bcb4449..13037e4 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -10,6 +10,8 @@ use syn::{ Block, FnArg, GenericArgument, + GenericParam, + Generics, ImplItem, ImplItemMethod, ItemTrait, @@ -22,6 +24,7 @@ use syn::{ TypeBareFn, TypeParamBound, Visibility, + WherePredicate, }; use crate::expectation::Expectation; @@ -174,6 +177,13 @@ fn get_type_replaced_impl_item_methods( mock_ident: &Ident, ) -> Vec<ImplItemMethod> { + let target_path = create_path!(Self); + + let replacement_path = Path::new( + WithLeadingColons::No, + [PathSegment::new(mock_ident.clone(), None)], + ); + impl_items .into_iter() .filter_map(|item| match item { @@ -186,11 +196,8 @@ fn get_type_replaced_impl_item_methods( FnArg::Typed(mut typed_arg) => { typed_arg.ty = Box::new(replace_path_in_type( *typed_arg.ty, - &create_path!(Self), - &Path::new( - WithLeadingColons::No, - [PathSegment::new(mock_ident.clone(), None)], - ), + &target_path, + &replacement_path, )); FnArg::Typed(typed_arg) @@ -205,16 +212,19 @@ fn get_type_replaced_impl_item_methods( r_arrow, Box::new(replace_path_in_type( *return_type, - &create_path!(Self), - &Path::new( - WithLeadingColons::No, - [PathSegment::new(mock_ident.clone(), None)], - ), + &target_path, + &replacement_path, )), ), ReturnType::Default => ReturnType::Default, }; + item_method.sig.generics = replace_path_in_generics( + item_method.sig.generics, + &target_path, + &replacement_path, + ); + Some(item_method) } _ => None, @@ -222,6 +232,71 @@ fn get_type_replaced_impl_item_methods( .collect() } +fn replace_path_in_generics( + mut generics: Generics, + target_path: &Path, + replacement_path: &Path, +) -> Generics +{ + generics.params = generics + .params + .into_iter() + .map(|generic_param| match generic_param { + GenericParam::Type(mut type_param) => { + type_param.bounds = type_param + .bounds + .into_iter() + .map(|bound| { + replace_type_param_bound_paths( + bound, + target_path, + replacement_path, + ) + }) + .collect(); + + GenericParam::Type(type_param) + } + generic_param => generic_param, + }) + .collect(); + + generics.where_clause = generics.where_clause.map(|mut where_clause| { + where_clause.predicates = where_clause + .predicates + .into_iter() + .map(|predicate| match predicate { + WherePredicate::Type(mut predicate_type) => { + predicate_type.bounded_ty = replace_path_in_type( + predicate_type.bounded_ty, + target_path, + replacement_path, + ); + + predicate_type.bounds = predicate_type + .bounds + .into_iter() + .map(|bound| { + replace_type_param_bound_paths( + bound, + target_path, + replacement_path, + ) + }) + .collect(); + + WherePredicate::Type(predicate_type) + } + predicate => predicate, + }) + .collect(); + + where_clause + }); + + generics +} + fn replace_path_in_type(ty: Type, target_path: &Path, replacement_path: &Path) -> Type { match ty { @@ -426,3 +501,24 @@ fn replace_type_bare_fn_type_paths( type_bare_fn } + +fn replace_type_param_bound_paths( + type_param_bound: TypeParamBound, + target_path: &Path, + replacement_path: &Path, +) -> TypeParamBound +{ + match type_param_bound { + TypeParamBound::Trait(mut trait_bound) => { + if &trait_bound.path == target_path { + trait_bound.path = replacement_path.clone(); + } else { + trait_bound.path = + replace_path_args(trait_bound.path, target_path, replacement_path); + } + + TypeParamBound::Trait(trait_bound) + } + TypeParamBound::Lifetime(lifetime) => TypeParamBound::Lifetime(lifetime), + } +} |