rbatis_macro_driver/macros/
sql_impl.rs1use crate::ParseArgs;
2use proc_macro2::{Ident, Span};
3use quote::quote;
4use quote::ToTokens;
5use syn::{FnArg, ItemFn, Pat};
6
7use crate::proc_macro::TokenStream;
8use crate::util::{find_fn_body, find_return_type, get_fn_args, is_query, is_rb_ref};
9
10pub(crate) fn impl_macro_sql(target_fn: &ItemFn, args: &ParseArgs) -> TokenStream {
12 let return_ty = find_return_type(target_fn);
13 let func_name_ident = target_fn.sig.ident.to_token_stream();
14
15 let mut rbatis_ident = "".to_token_stream();
16 let mut rbatis_name = String::new();
17 for x in &target_fn.sig.inputs {
18 match x {
19 FnArg::Receiver(_) => {}
20 FnArg::Typed(t) => {
21 let ty_stream = t.ty.to_token_stream().to_string();
22 if is_rb_ref(&ty_stream) {
23 rbatis_ident = t.pat.to_token_stream();
24 rbatis_name = rbatis_ident
25 .to_string()
26 .trim_start_matches("mut ")
27 .to_string();
28 break;
29 }
30 }
31 }
32 }
33
34 let mut sql_ident = quote!();
35 if args.sqls.len() >= 1 {
36 if rbatis_name.is_empty() {
37 panic!("[rb] you should add rbatis ref param `rb:&dyn Executor` on '{}()'!", target_fn.sig.ident);
38 }
39 let mut s = "".to_string();
40 for v in &args.sqls {
41 s = s + v.value().as_str();
42 }
43 sql_ident = quote!(#s);
44 } else {
45 panic!("[rb] Incorrect macro parameter length!");
46 }
47
48 let func_args_stream = target_fn.sig.inputs.to_token_stream();
49 let fn_body = find_fn_body(target_fn);
50 let is_async = target_fn.sig.asyncness.is_some();
51 if !is_async {
52 panic!(
53 "[rbaits] 'fn {}({})' must be async fn! ",
54 func_name_ident, func_args_stream
55 );
56 }
57 if rbatis_ident.to_string().starts_with("mut ") {
58 rbatis_ident = Ident::new(
59 &rbatis_ident.to_string().trim_start_matches("mut "),
60 Span::call_site(),
61 )
62 .to_token_stream();
63 }
64 let mut decode = quote! {};
65 let mut call_method = quote! {};
66 let is_query = is_query(&return_ty.to_string());
67 if is_query {
68 call_method = quote! {query};
69 decode = quote! { Ok(rbatis::decode::decode(r)?)}
70 } else {
71 call_method = quote! {exec};
72 decode = quote! { Ok(r)}
73 }
74 let page_req_str = String::new();
76 let page_req = quote! {};
77 let sql_args_gen =
79 filter_args_context_id(&rbatis_name, &get_fn_args(target_fn), &[page_req_str]);
80 let generic = target_fn.sig.generics.clone();
81 let gen_token_temple = quote! {
83 pub async fn #func_name_ident #generic(#func_args_stream) -> #return_ty{
84 let mut rb_args =vec![];
85 #sql_args_gen
86 #fn_body
87 use rbatis::executor::{Executor};
88 let r= #rbatis_ident.#call_method(&#sql_ident,rb_args #page_req).await?;
89 #decode
90 }
91 };
92 return gen_token_temple.into();
93}
94
95fn filter_args_context_id(
96 rbatis_name: &str,
97 fn_arg_name_vec: &Vec<Box<Pat>>,
98 skip_names: &[String],
99) -> proc_macro2::TokenStream {
100 let mut sql_args_gen = quote! {};
101 for item in fn_arg_name_vec {
102 let item_ident_name = item
103 .to_token_stream()
104 .to_string()
105 .trim()
106 .trim_start_matches("mut ")
107 .to_string();
108 if item_ident_name.eq(rbatis_name) {
109 continue;
110 }
111 let mut do_continue = false;
112 for x in skip_names {
113 if x.eq(&item_ident_name) {
114 do_continue = true;
115 break;
116 }
117 }
118 if do_continue {
119 continue;
120 }
121 sql_args_gen = quote! {
122 #sql_args_gen
123 rb_args.push(rbs::value(#item)?);
124 };
125 }
126 sql_args_gen
127}