summaryrefslogtreecommitdiff
path: root/macros/src/mock_input.rs
blob: 590ca0c9bfbb6a45d8cf27e64af89c6d64d26d99 (plain)
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
use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::{braced, Ident, ItemImpl, Path, Type, TypePath, WhereClause};

pub struct MockInput
{
    pub mock: Ident,
    pub mocked_trait: Path,
    pub item_impl: ItemImpl,
}

impl Parse for MockInput
{
    fn parse(input: ParseStream) -> Result<Self, syn::Error>
    {
        let mock = input.parse::<Ident>()?;

        let _generics = input.parse::<Option<WhereClause>>()?;

        let _braced_content;

        let _brace = braced!(_braced_content in input);

        let item_impl = input.parse::<ItemImpl>()?;

        let Some((_, mocked_trait, _)) = &item_impl.trait_ else {
            return Err(syn::Error::new(item_impl.impl_token.span, "Impl must be of a trait"));
        };

        if !matches!(
            item_impl.self_ty.as_ref(),
            Type::Path(TypePath {
                qself: None,
                path
            }) if path.is_ident(&mock)
        ) {
            return Err(syn::Error::new(
                item_impl.self_ty.span(),
                "Expected this to be the mock",
            ));
        }

        Ok(Self {
            mock,
            mocked_trait: mocked_trait.clone(),
            item_impl,
        })
    }
}