@@ -9,9 +9,9 @@ use quote::{quote, quote_spanned};
9
9
use syn:: { parse_macro_input, spanned:: Spanned , DeriveInput } ;
10
10
use type_paths:: { godot_types, string_name_ty, variant_ty} ;
11
11
12
- use crate :: attribute_ops:: FieldExportOps ;
12
+ use crate :: attribute_ops:: { FieldExportOps , PropertyOpts } ;
13
13
14
- #[ proc_macro_derive( GodotScript , attributes( export, script) ) ]
14
+ #[ proc_macro_derive( GodotScript , attributes( export, script, prop ) ) ]
15
15
pub fn derive ( input : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
16
16
let input = parse_macro_input ! ( input as DeriveInput ) ;
17
17
@@ -30,9 +30,10 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
30
30
let script_type_ident = opts. ident ;
31
31
let fields = opts. data . take_struct ( ) . unwrap ( ) . fields ;
32
32
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
+ } ) ;
36
37
37
38
let field_metadata_result: Result < TokenStream , TokenStream > = public_fields
38
39
. clone ( )
@@ -184,12 +185,23 @@ fn derive_get_fields<'a>(public_fields: impl Iterator<Item = &'a FieldOpts> + 'a
184
185
let variant_ty = variant_ty ( ) ;
185
186
186
187
let get_field_dispatch: TokenStream = public_fields
187
- . filter_map ( |field| field. ident . as_ref ( ) )
188
+ . filter ( |field| field. ident . is_some ( ) )
188
189
. 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
+ } ;
190
202
191
203
quote ! {
192
- #field_name => Some ( #godot_types:: prelude:: ToGodot :: to_variant( & self . #field ) ) ,
204
+ #field_name => Some ( #godot_types:: prelude:: ToGodot :: to_variant( & #accessor ) ) ,
193
205
}
194
206
} )
195
207
. collect ( ) ;
@@ -211,13 +223,26 @@ fn derive_set_fields<'a>(public_fields: impl Iterator<Item = &'a FieldOpts> + 'a
211
223
let godot_types = godot_types ( ) ;
212
224
213
225
let set_field_dispatch: TokenStream = public_fields
214
- . filter_map ( |field| field. ident . as_ref ( ) )
226
+ . filter ( |field| field. ident . is_some ( ) )
215
227
. 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
+ } ;
217
242
218
243
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 ,
221
246
}
222
247
} )
223
248
. collect ( ) ;
0 commit comments