1use proc_macro::TokenStream;
4use proc_macro2::{Ident, Span};
5use quote::quote;
6use syn::{ExprCall, ExprPath, Path, PathSegment};
7
8#[proc_macro]
21pub fn bind(input: TokenStream) -> TokenStream {
22 let input: proc_macro2::TokenStream = input.into();
23 let mut call: ExprCall = syn::parse2(input).unwrap();
24
25 let placeholders = call
28 .args
29 .pairs_mut()
30 .filter_map(|pair| {
31 let value = pair.into_value();
32 matches!(value, syn::Expr::Infer(_)).then_some(value)
33 })
34 .enumerate()
35 .map(|(i, underscore)| {
36 let ident = format!("__{}", i);
38 let ident = Ident::new(&ident, Span::call_site());
39 let segment = PathSegment::from(ident);
40 let path = Path::from(segment);
41 let expr_path = ExprPath {
42 attrs: Vec::new(),
43 qself: None,
44 path,
45 };
46 *underscore = expr_path.clone().into();
47 expr_path
48 })
49 .collect::<Vec<_>>();
50
51 quote! {
52 |#(#placeholders),*| { #call }
53 }
54 .into()
55}