hooks_derive_core/
detected.rs1use proc_macro2::{Span, TokenStream};
2use quote::{quote, quote_spanned, ToTokens};
3
4pub struct DetectedHooksTokens {
5 pub data_expr: TokenStream,
6 pub fn_arg_data_pat: TokenStream,
7 pub fn_stmts_extract_data: Option<TokenStream>,
8}
9
10pub struct DetectedHookCall {
11 pub ident: syn::Ident,
12 pub expr_call: syn::ExprCall,
13}
14
15pub fn detected_hooks_to_tokens(
17 mut used_hooks: Vec<DetectedHookCall>,
18 hooks_core_path: impl ToTokens,
19 expr_no_data: TokenStream,
20 ty_no_data: Option<TokenStream>,
21 span: Span,
22) -> DetectedHooksTokens {
23 match used_hooks.len() {
24 0 => DetectedHooksTokens {
25 data_expr: expr_no_data,
26 fn_arg_data_pat: {
27 let ty_no_data = ty_no_data.unwrap_or_else(|| quote!(_));
28 quote! {_: ::core::pin::Pin<&mut #ty_no_data>}
29 },
30 fn_stmts_extract_data: None,
31 },
32 1 => {
33 let h = used_hooks.pop().unwrap();
34 DetectedHooksTokens {
35 data_expr: h.expr_call.into_token_stream(),
36 fn_arg_data_pat: h.ident.into_token_stream(),
37 fn_stmts_extract_data: None,
38 }
39 }
40 _ => {
41 let expr_hooks_data = {
42 let mut used_hooks = used_hooks.iter().map(|h| &h.expr_call);
43 let first = used_hooks.next().unwrap();
44 let second = used_hooks.next().unwrap();
45
46 quote_spanned! { span =>
47 #hooks_core_path ::hook_pair::HookPair::new(#first , #second)
48 #( .chain( #used_hooks ) )*
49 }
50 };
51
52 let ident_hooks_data = syn::Ident::new("__hooks_data", span);
53
54 let impl_extract_hooks_data = {
55 let mut stmts = Vec::with_capacity(used_hooks.len());
56
57 while let Some(used_hook) = used_hooks.pop() {
58 let used_hook_ident = used_hook.ident;
59 let stmt = if !used_hooks.is_empty() {
60 quote_spanned! { span =>
61 let (#ident_hooks_data, #used_hook_ident) = #ident_hooks_data.pin_project();
62 }
63 } else {
64 quote_spanned! { span =>
66 let #used_hook_ident = #ident_hooks_data;
67 }
68 };
69 stmts.push(stmt);
70 }
71
72 proc_macro2::TokenStream::from_iter(stmts)
73 };
74
75 DetectedHooksTokens {
76 data_expr: expr_hooks_data,
77 fn_arg_data_pat: ident_hooks_data.into_token_stream(),
78 fn_stmts_extract_data: Some(impl_extract_hooks_data),
79 }
80 }
81 }
82}