@@ -2,10 +2,10 @@ use proc_macro::TokenStream;
2
2
use proc_macro2:: TokenStream as TokenStream2 ;
3
3
4
4
use syn:: spanned:: Spanned ;
5
- use syn:: { Data , DeriveInput , Fields , Ident , Meta , MetaList , NestedMeta , Path , Stmt , Type } ;
5
+ use syn:: { Data , DeriveInput , Expr , Fields , Ident , Meta , MetaList , NestedMeta , Path , Stmt , Type } ;
6
6
7
7
mod property_args;
8
- use property_args:: { PropertyAttrArgs , PropertyAttrArgsBuilder } ;
8
+ use property_args:: { PropertyAttrArgs , PropertyAttrArgsBuilder , PropertyGet , PropertySet } ;
9
9
10
10
pub ( crate ) struct DeriveData {
11
11
pub ( crate ) name : Ident ,
@@ -66,46 +66,70 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result<TokenStr
66
66
. default
67
67
. map ( |default_value| quote ! ( . with_default( #default_value) ) ) ;
68
68
let with_hint = config. hint . map ( |hint_fn| quote ! ( . with_hint( #hint_fn( ) ) ) ) ;
69
-
70
69
let with_usage = if config. no_editor {
71
70
Some ( quote ! ( . with_usage( :: gdnative:: export:: PropertyUsage :: NOEDITOR ) ) )
72
71
} else {
73
72
None
74
73
} ;
75
-
74
+ // if both of them are not set, i.e. `#[property]`. implicitly use both getter/setter
75
+ let ( get, set) = if config. get . is_none ( ) && config. set . is_none ( ) {
76
+ ( Some ( PropertyGet :: Default ) , Some ( PropertySet :: Default ) )
77
+ } else {
78
+ ( config. get , config. set )
79
+ } ;
76
80
let before_get: Option < Stmt > = config
77
81
. before_get
78
82
. map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
79
-
80
83
let after_get: Option < Stmt > = config
81
84
. after_get
82
85
. map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
83
-
86
+ let with_getter = get. map ( |get| {
87
+ let register_fn = match get {
88
+ PropertyGet :: Owned ( _) => quote ! ( with_getter) ,
89
+ _ => quote ! ( with_ref_getter) ,
90
+ } ;
91
+ let get: Expr = match get {
92
+ PropertyGet :: Default => parse_quote ! ( & this. #ident) ,
93
+ PropertyGet :: Owned ( path_expr) | PropertyGet :: Ref ( path_expr) => {
94
+ parse_quote ! ( #path_expr( this, _owner) )
95
+ }
96
+ } ;
97
+ quote ! (
98
+ . #register_fn( |this: & #name, _owner: :: gdnative:: object:: TRef <Self :: Base >| {
99
+ #before_get
100
+ let res = #get;
101
+ #after_get
102
+ res
103
+ } )
104
+ )
105
+ } ) ;
84
106
let before_set: Option < Stmt > = config
85
107
. before_set
86
108
. map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
87
-
88
109
let after_set: Option < Stmt > = config
89
110
. after_set
90
111
. map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
112
+ let with_setter = set. map ( |set| {
113
+ let set: Stmt = match set {
114
+ PropertySet :: Default => parse_quote ! ( this. #ident = v; ) ,
115
+ PropertySet :: WithPath ( path_expr) => parse_quote ! ( #path_expr( this, _owner, v) ; ) ,
116
+ } ;
117
+ quote ! (
118
+ . with_setter( |this: & mut #name, _owner: :: gdnative:: object:: TRef <Self :: Base >, v| {
119
+ #before_set
120
+ #set
121
+ #after_set
122
+ } ) )
123
+ } ) ;
91
124
92
125
let label = config. path . unwrap_or_else ( || format ! ( "{}" , ident) ) ;
93
126
quote ! ( {
94
127
builder. property( #label)
95
128
#with_default
96
129
#with_hint
97
130
#with_usage
98
- . with_ref_getter( |this: & #name, _owner: :: gdnative:: object:: TRef <Self :: Base >| {
99
- #before_get
100
- let res = & this. #ident;
101
- #after_get
102
- res
103
- } )
104
- . with_setter( |this: & mut #name, _owner: :: gdnative:: object:: TRef <Self :: Base >, v| {
105
- #before_set
106
- this. #ident = v;
107
- #after_set
108
- } )
131
+ #with_getter
132
+ #with_setter
109
133
. done( ) ;
110
134
} )
111
135
} ) ;
@@ -221,8 +245,8 @@ fn parse_derive_input(input: &DeriveInput) -> Result<DeriveData, syn::Error> {
221
245
222
246
match meta {
223
247
Meta :: List ( MetaList { nested, .. } ) => {
224
- let attr_args_builder =
225
- property_args . get_or_insert_with ( PropertyAttrArgsBuilder :: default ) ;
248
+ let attr_args_builder = property_args
249
+ . get_or_insert_with ( || PropertyAttrArgsBuilder :: new ( & field . ty ) ) ;
226
250
227
251
for arg in & nested {
228
252
if let NestedMeta :: Meta ( Meta :: NameValue ( ref pair) ) = arg {
@@ -236,7 +260,8 @@ fn parse_derive_input(input: &DeriveInput) -> Result<DeriveData, syn::Error> {
236
260
}
237
261
}
238
262
Meta :: Path ( _) => {
239
- property_args. get_or_insert_with ( PropertyAttrArgsBuilder :: default) ;
263
+ property_args
264
+ . get_or_insert_with ( || PropertyAttrArgsBuilder :: new ( & field. ty ) ) ;
240
265
}
241
266
m => {
242
267
let msg = format ! ( "Unexpected meta variant: {:?}" , m) ;
@@ -337,4 +362,49 @@ mod tests {
337
362
338
363
parse_derive_input ( & input) . unwrap ( ) ;
339
364
}
365
+
366
+ #[ test]
367
+ fn derive_property_get_set ( ) {
368
+ let input: TokenStream2 = syn:: parse_str (
369
+ r#"
370
+ #[inherit(Node)]
371
+ struct Foo {
372
+ #[property(get = "get_bar", set = "set_bar")]
373
+ bar: i64,
374
+ }"# ,
375
+ )
376
+ . unwrap ( ) ;
377
+ let input: DeriveInput = syn:: parse2 ( input) . unwrap ( ) ;
378
+ parse_derive_input ( & input) . unwrap ( ) ;
379
+ }
380
+
381
+ #[ test]
382
+ fn derive_property_default_get_set ( ) {
383
+ let input: TokenStream2 = syn:: parse_str (
384
+ r#"
385
+ #[inherit(Node)]
386
+ struct Foo {
387
+ #[property(get, set)]
388
+ bar: i64,
389
+ }"# ,
390
+ )
391
+ . unwrap ( ) ;
392
+ let input: DeriveInput = syn:: parse2 ( input) . unwrap ( ) ;
393
+ parse_derive_input ( & input) . unwrap ( ) ;
394
+ }
395
+
396
+ #[ test]
397
+ fn derive_property_default_get_ref ( ) {
398
+ let input: TokenStream2 = syn:: parse_str (
399
+ r#"
400
+ #[inherit(Node)]
401
+ struct Foo {
402
+ #[property(get_ref = "Self::get_bar")]
403
+ bar: i64,
404
+ }"# ,
405
+ )
406
+ . unwrap ( ) ;
407
+ let input: DeriveInput = syn:: parse2 ( input) . unwrap ( ) ;
408
+ parse_derive_input ( & input) . unwrap ( ) ;
409
+ }
340
410
}
0 commit comments