aboutsummaryrefslogtreecommitdiff
path: root/macros/src/fn_trait.rs
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/fn_trait.rs')
-rw-r--r--macros/src/fn_trait.rs91
1 files changed, 90 insertions, 1 deletions
diff --git a/macros/src/fn_trait.rs b/macros/src/fn_trait.rs
index 9820f02..a52a00d 100644
--- a/macros/src/fn_trait.rs
+++ b/macros/src/fn_trait.rs
@@ -5,7 +5,7 @@ use syn::token::Paren;
use syn::{parenthesized, parse_str, Ident, Token, TraitBound, Type};
/// A function trait. `dyn Fn(u32) -> String`
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FnTrait
{
pub dyn_token: Token![dyn],
@@ -84,3 +84,92 @@ impl ToTokens for FnTrait
}
}
}
+
+#[cfg(test)]
+mod tests
+{
+ use std::error::Error;
+
+ use quote::{format_ident, quote};
+ use syn::token::{Dyn, RArrow};
+ use syn::{parse2, Path, PathSegment, TypePath};
+
+ use super::*;
+
+ fn create_path(segments: &[PathSegment]) -> Path
+ {
+ Path {
+ leading_colon: None,
+ segments: segments.iter().cloned().collect(),
+ }
+ }
+
+ fn create_type(path: Path) -> Type
+ {
+ Type::Path(TypePath { qself: None, path })
+ }
+
+ #[test]
+ fn can_parse_fn_trait() -> Result<(), Box<dyn Error>>
+ {
+ assert_eq!(
+ parse2::<FnTrait>(quote! {
+ dyn Fn(String, u32) -> Handle
+ })?,
+ FnTrait {
+ dyn_token: Dyn::default(),
+ trait_ident: format_ident!("Fn"),
+ paren_token: Paren::default(),
+ inputs: Punctuated::from_iter(vec![
+ create_type(create_path(&[PathSegment::from(format_ident!(
+ "String"
+ ))])),
+ create_type(create_path(&[PathSegment::from(format_ident!("u32"))]))
+ ]),
+ r_arrow_token: RArrow::default(),
+ output: create_type(create_path(&[PathSegment::from(format_ident!(
+ "Handle"
+ ))])),
+ trait_bounds: Punctuated::new()
+ }
+ );
+
+ assert!(parse2::<FnTrait>(quote! {
+ Fn(u32) -> Handle
+ })
+ .is_err());
+
+ Ok(())
+ }
+
+ #[test]
+ fn can_parse_fn_trait_to_tokens()
+ {
+ assert_eq!(
+ FnTrait {
+ dyn_token: Dyn::default(),
+ trait_ident: format_ident!("Fn"),
+ paren_token: Paren::default(),
+ inputs: Punctuated::from_iter(vec![
+ create_type(create_path(&[PathSegment::from(format_ident!(
+ "Bread"
+ ))])),
+ create_type(create_path(&[PathSegment::from(format_ident!(
+ "Cheese"
+ ))])),
+ create_type(create_path(&[PathSegment::from(format_ident!(
+ "Tomatoes"
+ ))]))
+ ]),
+ r_arrow_token: RArrow::default(),
+ output: create_type(create_path(&[PathSegment::from(format_ident!(
+ "Taco"
+ ))])),
+ trait_bounds: Punctuated::new()
+ }
+ .into_token_stream()
+ .to_string(),
+ "dyn Fn (Bread , Cheese , Tomatoes) -> Taco".to_string()
+ );
+ }
+}