Skip to content

Commit a3bede0

Browse files
authored
Setters and Getters (#11)
1 parent 769ebb3 commit a3bede0

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

derive/src/attribute_ops.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ enum ExpEasingOpts {
246246
}
247247

248248
#[derive(FromField, Debug)]
249-
#[darling(forward_attrs(export))]
249+
#[darling(forward_attrs(export, prop))]
250250
pub struct FieldOpts {
251251
pub ident: Option<syn::Ident>,
252252
pub attrs: Vec<syn::Attribute>,
@@ -261,3 +261,10 @@ pub struct GodotScriptOpts {
261261
pub data: Data<util::Ignored, FieldOpts>,
262262
pub base: Option<syn::Ident>,
263263
}
264+
265+
#[derive(FromAttributes, Debug)]
266+
#[darling(attributes(prop))]
267+
pub struct PropertyOpts {
268+
pub get: Option<syn::Expr>,
269+
pub set: Option<syn::Expr>,
270+
}

derive/src/lib.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use quote::{quote, quote_spanned};
99
use syn::{parse_macro_input, spanned::Spanned, DeriveInput};
1010
use type_paths::{godot_types, string_name_ty, variant_ty};
1111

12-
use crate::attribute_ops::FieldExportOps;
12+
use crate::attribute_ops::{FieldExportOps, PropertyOpts};
1313

14-
#[proc_macro_derive(GodotScript, attributes(export, script))]
14+
#[proc_macro_derive(GodotScript, attributes(export, script, prop))]
1515
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
1616
let input = parse_macro_input!(input as DeriveInput);
1717

@@ -30,9 +30,10 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3030
let script_type_ident = opts.ident;
3131
let fields = opts.data.take_struct().unwrap().fields;
3232

33-
let public_fields = fields
34-
.iter()
35-
.filter(|field| matches!(field.vis, syn::Visibility::Public(_)));
33+
let public_fields = fields.iter().filter(|field| {
34+
matches!(field.vis, syn::Visibility::Public(_))
35+
|| field.attrs.iter().any(|attr| attr.path().is_ident("prop"))
36+
});
3637

3738
let field_metadata_result: Result<TokenStream, TokenStream> = public_fields
3839
.clone()
@@ -184,12 +185,23 @@ fn derive_get_fields<'a>(public_fields: impl Iterator<Item = &'a FieldOpts> + 'a
184185
let variant_ty = variant_ty();
185186

186187
let get_field_dispatch: TokenStream = public_fields
187-
.filter_map(|field| field.ident.as_ref())
188+
.filter(|field| field.ident.is_some())
188189
.map(|field| {
189-
let field_name = field.to_string();
190+
let field_ident = field.ident.as_ref().unwrap();
191+
let field_name = field_ident.to_string();
192+
193+
let opts = match PropertyOpts::from_attributes(&field.attrs) {
194+
Ok(opts) => opts,
195+
Err(err) => return err.write_errors(),
196+
};
197+
198+
let accessor = match opts.get {
199+
Some(getter) => quote_spanned!(getter.span() => #getter(&self)),
200+
None => quote!(self.#field_ident),
201+
};
190202

191203
quote! {
192-
#field_name => Some(#godot_types::prelude::ToGodot::to_variant(&self.#field)),
204+
#field_name => Some(#godot_types::prelude::ToGodot::to_variant(&#accessor)),
193205
}
194206
})
195207
.collect();
@@ -211,13 +223,26 @@ fn derive_set_fields<'a>(public_fields: impl Iterator<Item = &'a FieldOpts> + 'a
211223
let godot_types = godot_types();
212224

213225
let set_field_dispatch: TokenStream = public_fields
214-
.filter_map(|field| field.ident.as_ref())
226+
.filter(|field| field.ident.is_some())
215227
.map(|field| {
216-
let field_name = field.to_string();
228+
let field_ident = field.ident.as_ref().unwrap();
229+
let field_name = field_ident.to_string();
230+
231+
let opts = match PropertyOpts::from_attributes(&field.attrs) {
232+
Ok(opts) => opts,
233+
Err(err) => return err.write_errors(),
234+
};
235+
236+
let variant_value = quote!(#godot_types::prelude::FromGodot::from_variant(&value));
237+
238+
let assignment = match opts.set {
239+
Some(setter) => quote_spanned!(setter.span() => #setter(self, #variant_value)),
240+
None => quote!(self.#field_ident = #variant_value),
241+
};
217242

218243
quote_spanned! {
219-
field.span() =>
220-
#field_name => self.#field = #godot_types::prelude::FromGodot::from_variant(&value),
244+
field_ident.span() =>
245+
#field_name => #assignment,
221246
}
222247
})
223248
.collect();

0 commit comments

Comments
 (0)