1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{FnArg, ItemFn};
4
5#[proc_macro_attribute]
6pub fn command(_: TokenStream, item: TokenStream) -> TokenStream {
7 let mut f: ItemFn = syn::parse(item).unwrap();
8 let mut ins = f.sig.inputs.clone();
9
10 ins[1] = {
12 let FnArg::Typed(opt) = &f.sig.inputs[1] else {
13 panic!("Cannot find the `opt` argument in the function signature.");
14 };
15
16 let opt_ty = &opt.ty;
17 syn::parse2(quote! { opt: impl Into<#opt_ty> }).unwrap()
18 };
19
20 assert!(matches!(f.vis, syn::Visibility::Public(_)));
22 f.vis = syn::Visibility::Inherited;
23
24 let name_ori = f.sig.ident;
26 f.sig.ident = format_ident!("__{}", name_ori);
27 let name_new = &f.sig.ident;
28
29 let rest_args = ins.iter().skip(2).map(|arg| match arg {
31 FnArg::Receiver(_) => unreachable!(),
32 FnArg::Typed(t) => &t.pat,
33 });
34
35 quote! {
36 #[inline]
37 pub fn #name_ori(#ins) { self.#name_new(opt.into(), #(#rest_args),*); }
38 #f
39 }
40 .into()
41}