odra_codegen/generator/module_impl/
reference.rs

1use derive_more::From;
2use odra_ir::module::{Constructor, Method, ModuleImpl};
3use proc_macro2::TokenStream;
4use quote::{format_ident, quote};
5
6use crate::{
7    generator::common::{self, build_ref},
8    GenerateCode
9};
10
11#[derive(From)]
12pub struct ContractReference<'a> {
13    contract: &'a ModuleImpl
14}
15
16as_ref_for_contract_impl_generator!(ContractReference);
17
18impl GenerateCode for ContractReference<'_> {
19    fn generate_code(&self) -> TokenStream {
20        let struct_ident = self.contract.ident();
21        let ref_ident = format_ident!("{}Ref", struct_ident);
22
23        let ref_entrypoints = build_entrypoints(self.contract.get_public_method_iter());
24
25        let ref_constructors = build_constructors(self.contract.get_constructor_iter());
26
27        let contract_ref = build_ref(&ref_ident, struct_ident);
28
29        quote! {
30            #contract_ref
31
32            impl #ref_ident {
33                #ref_entrypoints
34
35                #ref_constructors
36            }
37        }
38    }
39}
40// check git history for more context
41fn build_entrypoints<'a, T>(methods: T) -> TokenStream
42where
43    T: Iterator<Item = &'a Method>
44{
45    methods
46        .map(|entrypoint| {
47            let attrs = &entrypoint.impl_item.attrs;
48            let sig = &entrypoint.full_sig;
49            let entrypoint_name = &entrypoint.ident.to_string();
50            let fn_body =
51                common::generate_fn_body(entrypoint.args.clone(), entrypoint_name, &entrypoint.ret);
52
53            quote! {
54                #(#attrs)*
55                pub #sig {
56                    #fn_body
57                }
58            }
59        })
60        .collect::<TokenStream>()
61}
62
63fn build_constructors<'a, T>(constructors: T) -> TokenStream
64where
65    T: Iterator<Item = &'a Constructor>
66{
67    constructors
68        .map(|constructor| {
69            let attrs = &constructor.impl_item.attrs;
70            let sig = &constructor.full_sig;
71            let constructor_name = constructor.ident.to_string();
72            let fn_body = common::generate_fn_body(
73                constructor.args.clone(),
74                &constructor_name,
75                &syn::ReturnType::Default
76            );
77
78            quote! {
79                #(#attrs)*
80                pub #sig {
81                    #fn_body
82                }
83            }
84        })
85        .collect::<TokenStream>()
86}