mockiato_codegen/
lib.rs

1//! Codegen for `mockiato`. Do not use this crate directly.
2
3#![recursion_limit = "128"]
4#![cfg_attr(rustc_is_nightly, feature(proc_macro_diagnostic))]
5#![warn(clippy::dbg_macro, clippy::unimplemented, unreachable_pub)]
6#![deny(
7    rust_2018_idioms,
8    future_incompatible,
9    missing_debug_implementations,
10    clippy::doc_markdown,
11    clippy::default_trait_access,
12    clippy::enum_glob_use,
13    clippy::needless_borrow,
14    clippy::large_digit_groups,
15    clippy::explicit_into_iter_loop
16)]
17
18mod code_generator;
19mod code_generator_impl;
20mod constant;
21mod controller_impl;
22mod diagnostic;
23mod emit_diagnostics;
24mod parse;
25mod result;
26mod syn_ext;
27
28use crate::code_generator_impl::{ArgumentsMatcherGeneratorImpl, CodeGeneratorImpl};
29use crate::controller_impl::ControllerImpl;
30use crate::emit_diagnostics::emit_diagnostics;
31use crate::parse::method_decl_parser::MethodDeclParserImpl;
32use crate::parse::method_inputs_parser::{
33    MethodArgParserImpl, MethodInputsParserImpl, MethodSelfArgParserImpl,
34};
35use crate::parse::mockable_attr_parser::MockableAttrParserImpl;
36use crate::parse::trait_decl_parser::TraitDeclParserImpl;
37use crate::result::Result;
38use proc_macro::TokenStream as ProcMacroTokenStream;
39use proc_macro2::TokenStream;
40use syn::{parse_macro_input, AttributeArgs, Item};
41
42pub(crate) trait Controller {
43    fn expand_mockable_trait(&self, attr: AttributeArgs, item: Item) -> Result<TokenStream>;
44}
45
46#[proc_macro_attribute]
47pub fn mockable(args: ProcMacroTokenStream, input: ProcMacroTokenStream) -> ProcMacroTokenStream {
48    let original_input = input.clone();
49
50    let attr = parse_macro_input!(args as AttributeArgs);
51    let item = parse_macro_input!(input as Item);
52
53    let controller = create_controller();
54    match controller.expand_mockable_trait(attr, item) {
55        Ok(output) => ProcMacroTokenStream::from(output),
56        Err(error) => {
57            let mut output = original_input;
58
59            let diagnostics_output = emit_diagnostics(error);
60            output.extend(ProcMacroTokenStream::from(diagnostics_output));
61
62            output
63        }
64    }
65}
66
67fn create_controller() -> impl Controller {
68    let mockable_attr_parser = Box::new(MockableAttrParserImpl::new());
69    let method_self_arg_parser = Box::new(MethodSelfArgParserImpl::new());
70    let method_arg_parser = Box::new(MethodArgParserImpl::new());
71    let method_inputs_parser = Box::new(MethodInputsParserImpl::new(
72        method_self_arg_parser,
73        method_arg_parser,
74    ));
75    let method_decl_parser = Box::new(MethodDeclParserImpl::new(method_inputs_parser));
76    let trait_decl_parser = Box::new(TraitDeclParserImpl::new(method_decl_parser));
77    let arguments_matcher_generator = Box::new(ArgumentsMatcherGeneratorImpl::new());
78    let code_generator = Box::new(CodeGeneratorImpl::new(arguments_matcher_generator));
79    ControllerImpl::new(mockable_attr_parser, trait_decl_parser, code_generator)
80}