Skip to content

Commit

Permalink
allow :: as generic arguments in impl signature
Browse files Browse the repository at this point in the history
also support multiple `impl` blocks for the same struct in the same module
  • Loading branch information
nrxus committed Sep 9, 2022
1 parent 4478d73 commit f694453
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 9 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# CHANGELOG

## v0.1.8
* Fix issue where a type with `::` could not be used as a generic
argument in an `impl` signature.
* Support multiple `impl` blocks for the same struct in the same
module
* This relies on the uniqueness of a uuid v4 which is technically
not guaranteed to be unique but pretty darn likely to be.

### Minor Breaking Change
* Bump MSRV to 1.56

## v0.1.7

* Don't change the parameter names in mocked methods if their pattern
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "faux"
version = "0.1.7"
version = "0.1.8"
authors = ["Andres <[email protected]>"]
license = "MIT"
description = "A library to mock structs"
Expand All @@ -12,7 +12,7 @@ readme = "README.md"
rust-version = "1.56"

[dependencies]
faux_macros = { path = "faux_macros", version = "0.1.7" }
faux_macros = { path = "faux_macros", version = "0.1.8" }
paste = "1.0.4"

[dev-dependencies]
Expand Down
3 changes: 2 additions & 1 deletion faux_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "faux_macros"
version = "0.1.7"
version = "0.1.8"
authors = ["Andres <[email protected]>"]
edition = "2021"
license = "MIT"
Expand All @@ -15,6 +15,7 @@ syn = { version = "1.0.58", features = ["full", "extra-traits"] }
quote = "1.0.8"
proc-macro2 = "1.0.24"
darling = "0.14"
uuid = { version = "0.8.2", features = ["v4"] }

[dev-dependencies]
faux = { path = "../" }
Expand Down
16 changes: 11 additions & 5 deletions faux_macros/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{create, self_type::SelfType};
use darling::FromMeta;
use morphed::Signature;
use quote::quote;
use syn::PathArguments;

#[derive(Default, FromMeta)]
#[darling(default)]
Expand Down Expand Up @@ -131,21 +132,23 @@ impl From<Mockable> for proc_macro::TokenStream {
real,
morphed,
whens,
real_ty,
mut real_ty,
morphed_ty,
} = mockable;

// create an identifier for the mod containing the real implementation
// this is necessary until we are allowed to introduce type aliases within impl blocks
let mod_ident = {
let uuid = uuid::Uuid::new_v4();
let ident = &real_ty.path.segments.last().unwrap().ident;
syn::Ident::new(
&match &real.trait_ {
None => format!("_faux_real_impl_{}", ident),
None => format!("_faux_real_impl_{}_{}", ident, uuid.to_simple()),
Some((_, trait_, _)) => format!(
"_faux_real_impl_{}_{}",
"_faux_real_impl_{}_{}_{}",
ident,
trait_.segments.last().unwrap().ident
trait_.segments.last().unwrap().ident,
uuid.to_simple()
),
},
proc_macro2::Span::call_site(),
Expand All @@ -164,6 +167,8 @@ impl From<Mockable> for proc_macro::TokenStream {
let alias = {
let mut path_to_ty = morphed_ty.path.segments;
let path_to_real_from_alias_mod = {
// let mut real_ty = real_ty.clone();
real_ty.path.segments.last_mut().unwrap().arguments = PathArguments::None;
let first_path = &real_ty.path.segments.first().unwrap().ident;
if *first_path == syn::Ident::new("crate", first_path.span()) {
// if it is an absolute position then no need to "super" up to find it
Expand All @@ -186,11 +191,12 @@ impl From<Mockable> for proc_macro::TokenStream {
quote! { pub(#(#supers)::*) }
};
let pathless_type = path_to_ty.pop().unwrap();
let ident = &pathless_type.value().ident;
quote! {
//do not warn for things like Foo<i32> = RealFoo<i32>
#[allow(non_camel_case_types)]
#[allow(clippy::builtin_type_shadow)]
#pub_supers type #pathless_type = #path_to_real_from_alias_mod;
#pub_supers use #path_to_real_from_alias_mod as #ident;
}
};

Expand Down
2 changes: 1 addition & 1 deletion faux_macros/src/methods/morphed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ impl<'a> Signature<'a> {
self.method_data
.as_ref()
.filter(|m| !m.is_private)
.map(|m| m.create_when(self.output, &self.name))
.map(|m| m.create_when(self.output, self.name))
}

fn wrap_self(
Expand Down
12 changes: 12 additions & 0 deletions tests/generic_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,21 @@ impl<'a, T: std::fmt::Debug, R> Generic<'a, T, R> {
}
}

#[faux::methods]
impl<'a, R> Generic<'a, i32, R> {
pub fn get_i32(&self) -> i32 {
self.a
}
}

#[test]
fn real() {
let hello = "hello".to_string();
let real = Generic::new(10, &hello);
assert_eq!(real.get(), &20);
assert_eq!(real.get_ref(), &10);
assert_eq!(real.life_ref(), &hello);
assert_eq!(real.get_i32(), 10);
}

#[test]
Expand All @@ -49,4 +57,8 @@ fn mocked() {

unsafe { faux::when!(fake.life_ref).then_unchecked(|_| &2) }
assert_eq!(fake.life_ref(), &2);

let mut int_fake: Generic<i32, u32> = Generic::faux();
faux::when!(int_fake.get_i32()).then_return(4);
assert_eq!(int_fake.get_i32(), 4);
}

0 comments on commit f694453

Please sign in to comment.