moq_derive 0.4.1

Mock generator (macro implementations)
Documentation
use proc_macro2_diagnostics::Diagnostic;
use quote::{quote, ToTokens};
use syn::{ItemTrait, TraitItem};

use crate::{
    action::{Action, ActionCollection},
    context::Context,
    mock::Mock,
    utils::Demoqifing,
};

pub fn automock_impl(
    args: proc_macro2::TokenStream,
    input: proc_macro2::TokenStream,
) -> Result<proc_macro2::TokenStream, Diagnostic> {
    let p = AutomockMacro::from_ast(args, input)?;
    let output = quote! { #p };

    Ok(output)
}

#[derive(Debug)]
pub struct AutomockMacro {
    trait_def: ItemTrait,
    actions_def: ActionCollection,
    actions: Vec<Action>,
    mock: Mock,
}

impl AutomockMacro {
    pub fn from_ast(
        args: proc_macro2::TokenStream,
        input: proc_macro2::TokenStream,
    ) -> Result<Self, syn::Error> {
        let cx = Context::from_ast(args, input)?;
        let actions_def = ActionCollection::from_ast(&cx)?;
        let actions = cx
            .trait_def
            .items
            .iter()
            .filter_map(|item| match item {
                TraitItem::Fn(item) => Some(item),
                _ => None,
            })
            .map(|trait_func| Action::from_ast(&cx, trait_func))
            .collect::<Result<_, _>>()?;
        let mock = Mock::from_ast(&cx)?;

        Ok(Self {
            trait_def: cx.trait_def.demoqified(),
            actions_def,
            actions,
            mock,
        })
    }
}

impl ToTokens for AutomockMacro {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        self.trait_def.to_tokens(tokens);
        self.actions_def.to_tokens(tokens);
        self.actions.iter().for_each(|act| act.to_tokens(tokens));
        self.mock.to_tokens(tokens);
    }
}