Skip to content

Commit c58a87e

Browse files
committed
Add the #[skip] attribute for skipping fields in FromVarargs.
This is useful mainly for skipping marker fields in generic code.
1 parent d0538f0 commit c58a87e

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

gdnative-derive/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,21 @@ pub fn derive_from_variant(input: TokenStream) -> TokenStream {
493493
/// #[opt] baz: Option<Ref<Node>>,
494494
/// }
495495
/// ```
496-
#[proc_macro_derive(FromVarargs, attributes(opt))]
496+
///
497+
/// ## Field attributes
498+
///
499+
/// Attributes can be used to customize behavior of certain fields. All attributes are optional.
500+
///
501+
/// ### `#[opt]`
502+
///
503+
/// Marks an argument as optional. Required arguments must precede all optional arguments.
504+
/// Default values are obtained through `Default::default`.
505+
///
506+
/// ### `#[skip]`
507+
///
508+
/// Instructs the macro to skip a field. Skipped fields do not affect the signature of the
509+
/// argument list. They may be located anywhere. Values are obtained through `Default::default`.
510+
#[proc_macro_derive(FromVarargs, attributes(opt, skip))]
497511
pub fn derive_from_varargs(input: TokenStream) -> TokenStream {
498512
let derive_input = syn::parse_macro_input!(input as syn::DeriveInput);
499513
match varargs::derive_from_varargs(derive_input) {

gdnative-derive/src/varargs.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ pub(crate) fn derive_from_varargs(input: DeriveInput) -> Result<TokenStream2, sy
4848

4949
let mut required = Vec::new();
5050
let mut optional = Vec::new();
51+
let mut skipped = Vec::new();
5152
for field in fields {
53+
if field.attrs.iter().any(|attr| attr.path.is_ident("skip")) {
54+
skipped.push(field);
55+
continue;
56+
}
57+
5258
let is_optional = field.attrs.iter().any(|attr| attr.path.is_ident("opt"));
5359
if !is_optional && !optional.is_empty() {
5460
return Err(syn::Error::new(
@@ -111,6 +117,16 @@ pub(crate) fn derive_from_varargs(input: DeriveInput) -> Result<TokenStream2, sy
111117
.map(|field| format!("{}", field.ty.to_token_stream()))
112118
.collect::<Vec<_>>();
113119

120+
let skipped_var_idents = skipped
121+
.iter()
122+
.enumerate()
123+
.map(|(n, field)| {
124+
field.ident.clone().unwrap_or_else(|| {
125+
Ident::new(&format!("__skipped_arg_{}", n), Span::call_site())
126+
})
127+
})
128+
.collect::<Vec<_>>();
129+
114130
Ok(quote! {
115131
#derived
116132
impl #generics ::gdnative::export::FromVarargs for #ident #generics #where_clause {
@@ -147,9 +163,14 @@ pub(crate) fn derive_from_varargs(input: DeriveInput) -> Result<TokenStream2, sy
147163
let #req_var_idents = #req_var_idents.unwrap();
148164
)*
149165

166+
#(
167+
let #skipped_var_idents = core::default::Default::default();
168+
)*
169+
150170
std::result::Result::Ok(#ident {
151171
#(#req_var_idents,)*
152172
#(#opt_var_idents,)*
173+
#(#skipped_var_idents,)*
153174
})
154175
}
155176
}

0 commit comments

Comments
 (0)