use proc_macro2::TokenStream as TokenStream2;
use quote::{ToTokens, quote_spanned};
use syn::{Ident, Pat, PatType, Type, ext::IdentExt, spanned::Spanned};
const RESERVED_ARGS: &[&str] = &["window", "state", "app_handle", "webview_window"];
pub(crate) struct Arg {
pat: PatType,
pub skip_type: bool,
}
impl Arg {
pub fn ty(&self) -> &Type {
&self.pat.ty
}
pub fn pat(&self) -> &Pat {
&self.pat.pat
}
pub fn span(&self) -> proc_macro2::Span {
self.pat.span()
}
}
impl From<PatType> for Arg {
fn from(mut pat: PatType) -> Self {
let mut skip_type = matches!(
pat.pat.as_ref(),
Pat::Ident(pat_ident) if RESERVED_ARGS.iter().any(|&s| pat_ident.ident == s)
);
pat.attrs = pat
.attrs
.into_iter()
.filter(|attr| {
if RESERVED_ARGS.iter().any(|s| attr.path().is_ident(s)) {
skip_type = true;
return false;
}
true
})
.collect::<Vec<_>>();
Self { pat, skip_type }
}
}
impl ToTokens for Arg {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.pat.to_tokens(tokens);
}
}
pub(crate) fn parse_args(
args: &[Arg],
message: &Ident,
proc_ident: &Ident,
) -> syn::Result<Vec<TokenStream2>> {
args.iter()
.map(|arg| parse_arg(arg, message, proc_ident))
.collect()
}
fn parse_arg(arg: &Arg, message: &Ident, proc_ident: &Ident) -> syn::Result<TokenStream2> {
let key = parse_arg_key(arg)?;
if key == "self" {
return Err(syn::Error::new(
key.span(),
"unable to use self as a command function parameter",
));
}
let arg_span = arg.span();
Ok(
quote_spanned!(arg_span=> ::tauri::ipc::CommandArg::from_command(
::tauri::ipc::CommandItem {
name: stringify!(#proc_ident),
key: #key,
message: &#message,
acl: &None,
plugin: None,
}
)),
)
}
pub(crate) fn parse_arg_key(arg: &Arg) -> Result<String, syn::Error> {
match arg.pat() {
Pat::Ident(arg) => Ok(arg.ident.unraw().to_string()),
Pat::Wild(_) => Ok("".into()), Pat::Struct(s) => Ok(s.path.segments.last().unwrap().ident.to_string()),
Pat::TupleStruct(s) => Ok(s.path.segments.last().unwrap().ident.to_string()),
err => Err(syn::Error::new(
err.span(),
"only named, wildcard, struct, and tuple struct arguments allowed",
)),
}
}