1#![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}