1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
use syn::{parse2, ItemType};
use crate::fn_trait::FnTrait;
pub struct FactoryTypeAlias
{
pub type_alias: ItemType,
pub factory_interface: FnTrait,
}
impl Parse for FactoryTypeAlias
{
fn parse(input: ParseStream) -> syn::Result<Self>
{
let type_alias = input
.parse::<ItemType>()
.map_err(|_| input.error("Expected a type alias"))?;
let aliased_fn_trait =
parse2::<FnTrait>(type_alias.ty.as_ref().to_token_stream())?;
Ok(Self {
type_alias,
factory_interface: aliased_fn_trait.clone(),
})
}
}
#[cfg(test)]
mod tests
{
use std::error::Error;
use quote::{format_ident, quote};
use syn::punctuated::Punctuated;
use syn::token::And;
use syn::{Type, TypeReference};
use super::*;
use crate::test_utils;
#[test]
fn can_parse() -> Result<(), Box<dyn Error>>
{
let input_args = quote! {
type FooFactory = dyn Fn(String, &u32) -> Foo;
};
let factory_type_alias = parse2::<FactoryTypeAlias>(input_args)?;
assert_eq!(
factory_type_alias.factory_interface.inputs,
Punctuated::from_iter(vec![
test_utils::create_type(test_utils::create_path(&[
test_utils::create_path_segment(format_ident!("String"), &[])
])),
Type::Reference(TypeReference {
and_token: And::default(),
lifetime: None,
mutability: None,
elem: Box::new(test_utils::create_type(test_utils::create_path(&[
test_utils::create_path_segment(format_ident!("u32"), &[])
])))
})
])
);
Ok(())
}
}
|