diff --git a/macros/src/command/mod.rs b/macros/src/command/mod.rs index 28fa97c50332..b54caf9430ff 100644 --- a/macros/src/command/mod.rs +++ b/macros/src/command/mod.rs @@ -79,7 +79,6 @@ struct ParamArgs { /// Part of the Invocation struct. Represents a single parameter of a Discord command. struct CommandParameter { - ident: syn::Ident, name: String, type_: syn::Type, args: ParamArgs, @@ -162,18 +161,14 @@ pub fn command( // Collect argument names/types/attributes to insert into generated function let mut parameters = Vec::new(); for command_param in function.sig.inputs.iter_mut().skip(1) { + let span = command_param.span(); + let pattern = match command_param { - syn::FnArg::Typed(x) => &mut *x, + syn::FnArg::Typed(x) => x, syn::FnArg::Receiver(r) => { return Err(syn::Error::new(r.span(), "self argument is invalid here").into()); } }; - let ident = match &*pattern.pat { - syn::Pat::Ident(pat_ident) => &pat_ident.ident, - x => { - return Err(syn::Error::new(x.span(), "must use an identifier pattern here").into()) - } - }; let attrs = pattern .attrs @@ -182,15 +177,19 @@ pub fn command( .collect::, _>>()?; let attrs = ::from_list(&attrs)?; + let name = if let Some(rename) = &attrs.rename { + rename.clone() + } else if let syn::Pat::Ident(ident) = &*pattern.pat { + ident.ident.to_string().trim_start_matches("r#").into() + } else { + let message = "#[rename = \"...\"] must be specified for pattern parameters"; + return Err(syn::Error::new(pattern.pat.span(), message).into()); + }; parameters.push(CommandParameter { - ident: ident.clone(), - name: attrs - .rename - .clone() - .unwrap_or_else(|| ident.to_string().trim_start_matches("r#").to_string()), + name, type_: (*pattern.ty).clone(), args: attrs, - span: command_param.span(), + span, }); } diff --git a/macros/src/command/prefix.rs b/macros/src/command/prefix.rs index 59d31e8b2048..f69f8958af04 100644 --- a/macros/src/command/prefix.rs +++ b/macros/src/command/prefix.rs @@ -1,4 +1,5 @@ use super::Invocation; +use quote::format_ident; use syn::spanned::Spanned as _; fn quote_parameter(p: &super::CommandParameter) -> Result { @@ -14,23 +15,20 @@ fn quote_parameter(p: &super::CommandParameter) -> Result Modifier::Rest, (false, false, true) => Modifier::Flag, _ => { - return Err(syn::Error::new( - p.span, - "modifiers like #[lazy] or #[rest] currently cannot be used together", - ) - .into()) + let message = "modifiers like #[lazy] or #[rest] currently cannot be used together"; + return Err(syn::Error::new(p.span, message)); } }; let type_ = &p.type_; Ok(match modifier { Modifier::Flag => { if p.type_ != syn::parse_quote! { bool } { - return Err(syn::Error::new(p.type_.span(), "Must use bool for flags").into()); + return Err(syn::Error::new(p.type_.span(), "Must use bool for flags")); } // TODO: doesn't work for r#keywords :( I cant be arsed to fix this rn because basically // nobody uses this feature anyways and I'd have to go change the macro_rules macro to // not accept non-quoted idents anymore - let literal = proc_macro2::Literal::string(&p.ident.to_string()); + let literal = proc_macro2::Literal::string(&p.name); quote::quote! { #[flag] (#literal) } } Modifier::Lazy => quote::quote! { #[lazy] (#type_) }, @@ -40,7 +38,9 @@ fn quote_parameter(p: &super::CommandParameter) -> Result Result { - let param_idents = inv.parameters.iter().map(|p| &p.ident).collect::>(); + let param_idents = (0..inv.parameters.len()) + .map(|i| format_ident!("poise_param_{i}")) + .collect::>(); let param_specs = inv .parameters .iter() @@ -52,7 +52,6 @@ pub fn generate_prefix_action(inv: &Invocation) -> Result diff --git a/macros/src/command/slash.rs b/macros/src/command/slash.rs index 94f2ce930124..7a4740eea6cb 100644 --- a/macros/src/command/slash.rs +++ b/macros/src/command/slash.rs @@ -1,5 +1,6 @@ use super::Invocation; use crate::util::extract_type_parameter; +use quote::format_ident; use syn::spanned::Spanned as _; pub fn generate_parameters(inv: &Invocation) -> Result, syn::Error> { @@ -143,7 +144,9 @@ pub fn generate_slash_action(inv: &Invocation) -> Result>(); + let param_identifiers = (0..inv.parameters.len()) + .map(|i| format_ident!("poise_param_{i}")) + .collect::>(); let param_names = inv.parameters.iter().map(|p| &p.name).collect::>(); let param_types = inv