use quote::quote;
use syn::ItemTrait;
use crate::{double_trait::double_trait, dummy_impl::dummy_impl};
pub fn expand(org_trait: ItemTrait) -> syn::Result<proc_macro2::TokenStream> {
let trait_with_dummies = double_trait(org_trait.ident.clone(), org_trait.clone())?;
let dummy_impl = dummy_impl(org_trait.ident.clone(), org_trait);
let token_stream = quote! {
#trait_with_dummies
#dummy_impl
};
Ok(token_stream)
}
#[cfg(test)]
mod tests {
use quote::quote;
use syn::{ItemTrait, parse2};
use super::expand;
#[test]
fn private_empty_trait() {
let empty_trait = given(quote! {
trait MyTrait {}
});
let output = expand(empty_trait).unwrap();
let expected = quote! {
trait MyTrait{}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string())
}
#[test]
fn public_empty_trait() {
let org_trait = given(quote! { pub trait MyTrait {} });
let output = expand(org_trait).unwrap();
let expected = quote! {
pub trait MyTrait {}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string());
}
#[test]
fn empty_default_method() {
let item = given(quote! {
trait MyTrait {
fn foobar(&self);
}
});
let output = expand(item).unwrap();
let expected = quote! {
trait MyTrait {
fn foobar(&self) {}
}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string());
}
#[test]
fn dummy_default_method() {
let item = given(quote! {
trait MyTrait {
fn foobar(&self) -> i32;
}
});
let output = expand(item).unwrap();
let expected = quote! {
trait MyTrait {
fn foobar(&self) -> i32 {
let double_trait_name = stringify!(MyTrait);
let fn_name = stringify!(foobar);
unimplemented!("{double_trait_name}::{fn_name}")
}
}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string());
}
#[test]
fn respect_existing_default_impl() {
let item = given(quote! {
pub trait MyTrait {
fn foobar() { println!("Hello Default!") }
}
});
let output = expand(item).unwrap();
let expected = quote! {
pub trait MyTrait {
fn foobar() { println!("Hello Default!") }
}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string());
}
#[test]
fn forward_async_method_with_unit_return() {
let item = given(quote! {
trait MyTrait {
async fn foobar(&self);
}
});
let output = expand(item).unwrap();
let expected = quote! {
trait MyTrait {
async fn foobar(&self) {}
}
impl MyTrait for double_trait::Dummy {}
};
assert_eq!(expected.to_string(), output.to_string());
}
fn given(item: proc_macro2::TokenStream) -> ItemTrait {
let item: ItemTrait = parse2(item).unwrap();
item
}
}