Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to double type aliases to mockall_double #374

Merged
merged 1 commit into from May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions mockall_double/CHANGELOG.md
@@ -0,0 +1,12 @@
# Change Log

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).


## [ Unreleased ] - ReleaseDate

### Added

- Added the ability to mock type aliases.
([#374](https://github.com/asomers/mockall/pull/374))
60 changes: 54 additions & 6 deletions mockall_double/src/lib.rs
Expand Up @@ -37,16 +37,23 @@ cfg_if! {
}

fn do_double(_attrs: TokenStream, input: TokenStream) -> TokenStream {
let mut use_stmt: ItemUse = match parse2(input.clone()) {
let mut item: Item = match parse2(input.clone()) {
Ok(u) => u,
Err(e) => return e.to_compile_error()
};
mock_itemuse(&mut use_stmt);
match &mut item {
Item::Use(use_stmt) => mock_itemuse(use_stmt),
Item::Type(item_type) => mock_itemtype(item_type),
_ => {
compile_error(item.span(),
"Only use statements and type aliases may be doubled");
}
};
quote!(
#[cfg(not(test))]
#input
#[cfg(test)]
#use_stmt
#item
)
}

Expand Down Expand Up @@ -105,6 +112,13 @@ fn do_double(_attrs: TokenStream, input: TokenStream) -> TokenStream {
/// Bean
/// };
/// ```
/// type aliases,
/// ```no_run
/// # mod bar { pub struct Baz {} }
/// # use mockall_double::double;
/// #[double]
/// type Foo = bar::Baz;
/// ```
/// and renamed imports, too. With renamed imports, it isn't even necessary to
/// declare a submodule.
/// ```no_run
Expand Down Expand Up @@ -146,6 +160,16 @@ pub fn double(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream)
do_double(attrs.into(), input.into()).into()
}

fn mock_itemtype(orig: &mut ItemType) {
match &mut *orig.ty {
Type::Path(tp) => {
let ident = &tp.path.segments.last_mut().unwrap().ident;
tp.path.segments.last_mut().unwrap().ident = mock_ident(ident);
}
x => compile_error(x.span(), "Only path types may be doubled")
}
}

fn mock_itemuse(orig: &mut ItemUse) {
if let UseTree::Name(un) = &orig.tree {
compile_error(un.span(),
Expand Down Expand Up @@ -279,6 +303,18 @@ mod double {
cmp("", code, expected);
}

#[test]
fn pub_use() {
let code = r#"pub use foo::bar;"#;
let expected = r#"
#[cfg(not(test))]
pub use foo::bar;
#[cfg(test)]
pub use foo::mock_bar as bar;
"#;
cmp("", code, expected);
}

#[test]
fn rename() {
let code = r#"use Foo as Bar;"#;
Expand All @@ -292,10 +328,22 @@ mod double {
}

#[test]
fn not_use_stmt() {
fn type_() {
let code = r#"type Foo = bar::Baz;"#;
let expected = r#"
#[cfg(not(test))]
type Foo = bar::Baz;
#[cfg(test)]
type Foo = bar::MockBaz;
"#;
cmp("", code, expected);
}

#[test]
#[should_panic(expected = "Only use statements and type aliases")]
fn undoubleable() {
let code = r#"struct Foo{}"#;
cmp("", code, "compile_error!{\"expected `use`\"}");
cmp("", code, "");
}
}
}