@@ -2,10 +2,10 @@ use proc_macro::TokenStream;
22use proc_macro2:: TokenStream as TokenStream2 ;
33
44use 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 } ;
66
77mod property_args;
8- use property_args:: { PropertyAttrArgs , PropertyAttrArgsBuilder } ;
8+ use property_args:: { PropertyAttrArgs , PropertyAttrArgsBuilder , PropertyGet , PropertySet } ;
99
1010pub ( crate ) struct DeriveData {
1111 pub ( crate ) name : Ident ,
@@ -66,46 +66,70 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result<TokenStr
6666 . default
6767 . map ( |default_value| quote ! ( . with_default( #default_value) ) ) ;
6868 let with_hint = config. hint . map ( |hint_fn| quote ! ( . with_hint( #hint_fn( ) ) ) ) ;
69-
7069 let with_usage = if config. no_editor {
7170 Some ( quote ! ( . with_usage( :: gdnative:: export:: PropertyUsage :: NOEDITOR ) ) )
7271 } else {
7372 None
7473 } ;
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+ } ;
7680 let before_get: Option < Stmt > = config
7781 . before_get
7882 . map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
79-
8083 let after_get: Option < Stmt > = config
8184 . after_get
8285 . 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+ } ) ;
84106 let before_set: Option < Stmt > = config
85107 . before_set
86108 . map ( |path_expr| parse_quote ! ( #path_expr( this, _owner) ; ) ) ;
87-
88109 let after_set: Option < Stmt > = config
89110 . after_set
90111 . 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+ } ) ;
91124
92125 let label = config. path . unwrap_or_else ( || format ! ( "{}" , ident) ) ;
93126 quote ! ( {
94127 builder. property( #label)
95128 #with_default
96129 #with_hint
97130 #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
109133 . done( ) ;
110134 } )
111135 } ) ;
@@ -221,8 +245,8 @@ fn parse_derive_input(input: &DeriveInput) -> Result<DeriveData, syn::Error> {
221245
222246 match meta {
223247 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 ) ) ;
226250
227251 for arg in & nested {
228252 if let NestedMeta :: Meta ( Meta :: NameValue ( ref pair) ) = arg {
@@ -236,7 +260,8 @@ fn parse_derive_input(input: &DeriveInput) -> Result<DeriveData, syn::Error> {
236260 }
237261 }
238262 Meta :: Path ( _) => {
239- property_args. get_or_insert_with ( PropertyAttrArgsBuilder :: default) ;
263+ property_args
264+ . get_or_insert_with ( || PropertyAttrArgsBuilder :: new ( & field. ty ) ) ;
240265 }
241266 m => {
242267 let msg = format ! ( "Unexpected meta variant: {:?}" , m) ;
@@ -337,4 +362,49 @@ mod tests {
337362
338363 parse_derive_input ( & input) . unwrap ( ) ;
339364 }
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+ }
340410}
0 commit comments