@@ -17,7 +17,7 @@ use type_paths::{godot_types, string_name_ty, variant_ty};
1717
1818use crate :: attribute_ops:: { FieldExportOps , PropertyOpts } ;
1919
20- #[ proc_macro_derive( GodotScript , attributes( export, script, prop) ) ]
20+ #[ proc_macro_derive( GodotScript , attributes( export, script, prop, signal ) ) ]
2121pub fn derive ( input : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
2222 let input = parse_macro_input ! ( input as DeriveInput ) ;
2323
@@ -41,8 +41,13 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
4141 || field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "prop" ) )
4242 } ) ;
4343
44+ let signal_fields = fields. iter ( ) . filter ( |field| {
45+ field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "signal" ) )
46+ } ) ;
47+
4448 let field_metadata_result: Result < TokenStream , TokenStream > = public_fields
4549 . clone ( )
50+ . filter ( |field| !field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "signal" ) ) )
4651 . map ( |field| {
4752 let name = field
4853 . ident
@@ -64,23 +69,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
6469 ops. hint ( field. ident . span ( ) ) ?
6570 } ;
6671
67- let description = field
68- . attrs
69- . iter ( )
70- . filter ( |attr| attr. path ( ) . is_ident ( "doc" ) )
71- . map ( |attr| {
72- attr. meta
73- . require_name_value ( )
74- . unwrap ( )
75- . value
76- . to_token_stream ( )
77- } )
78- . reduce ( |mut acc, comment| {
79- acc. extend ( quote ! ( , "\n " , ) ) ;
80- acc. extend ( comment) ;
81- acc
82- } ) ;
83-
72+ let description = get_field_description ( field) ;
8473 let item = quote ! {
8574 :: godot_rust_script:: RustScriptPropDesc {
8675 name: #name,
@@ -101,7 +90,21 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
10190 Err ( err) => return err. into ( ) ,
10291 } ;
10392
104- let get_fields_impl = derive_get_fields ( public_fields. clone ( ) ) ;
93+ let signal_metadata_result: TokenStream = signal_fields. clone ( ) . map ( |field| {
94+ let signal_name = field. ident . as_ref ( ) . map ( |ident| ident. to_string ( ) ) . unwrap_or_default ( ) ;
95+ let signal_description = get_field_description ( field) ;
96+ let signal_type = & field. ty ;
97+
98+ quote ! {
99+ :: godot_rust_script:: RustScriptSignalDesc {
100+ name: #signal_name,
101+ arguments: <#signal_type as :: godot_rust_script:: ScriptSignal >:: argument_desc( ) ,
102+ description: concat!( #signal_description) ,
103+ } ,
104+ }
105+ } ) . collect ( ) ;
106+
107+ let get_fields_impl = derive_get_fields ( public_fields. clone ( ) . chain ( signal_fields) ) ;
105108 let set_fields_impl = derive_set_fields ( public_fields. clone ( ) ) ;
106109 let properties_state_impl = derive_property_states_export ( public_fields) ;
107110 let default_impl = derive_default_with_base ( & fields) ;
@@ -122,7 +125,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
122125 acc. extend ( lit) ;
123126 acc
124127 } ) ;
125-
128+
126129 let output = quote ! {
127130 impl :: godot_rust_script:: GodotScript for #script_type_ident {
128131 #get_fields_impl
@@ -148,6 +151,9 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
148151 concat!( #description) ,
149152 vec![
150153 #field_metadata
154+ ] ,
155+ vec![
156+ #signal_metadata_result
151157 ]
152158 ) ;
153159
@@ -205,8 +211,13 @@ fn derive_default_with_base(field_opts: &[FieldOpts]) -> TokenStream {
205211 . iter ( )
206212 . filter_map ( |field| match field. ident . as_ref ( ) {
207213 Some ( ident) if * ident == "base" => {
208- Some ( quote_spanned ! ( ident. span( ) => #ident: base. cast( ) , ) )
214+ Some ( quote_spanned ! ( ident. span( ) => #ident: base. clone( ) . cast( ) , ) )
215+ } ,
216+
217+ Some ( ident) if field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "signal" ) ) => {
218+ Some ( quote_spanned ! ( ident. span( ) => #ident: :: godot_rust_script:: ScriptSignal :: new( base. clone( ) , stringify!( #ident) ) , ) )
209219 }
220+
210221 Some ( ident) => Some ( quote_spanned ! ( ident. span( ) => #ident: Default :: default ( ) , ) ) ,
211222 None => None ,
212223 } )
@@ -335,6 +346,25 @@ fn derive_property_states_export<'a>(
335346 }
336347}
337348
349+ fn get_field_description ( field : & FieldOpts ) -> Option < TokenStream > {
350+ field
351+ . attrs
352+ . iter ( )
353+ . filter ( |attr| attr. path ( ) . is_ident ( "doc" ) )
354+ . map ( |attr| {
355+ attr. meta
356+ . require_name_value ( )
357+ . unwrap ( )
358+ . value
359+ . to_token_stream ( )
360+ } )
361+ . reduce ( |mut acc, comment| {
362+ acc. extend ( quote ! ( , "\n " , ) ) ;
363+ acc. extend ( comment) ;
364+ acc
365+ } )
366+ }
367+
338368#[ proc_macro_attribute]
339369pub fn godot_script_impl (
340370 args : proc_macro:: TokenStream ,
0 commit comments