@@ -17,7 +17,7 @@ use type_paths::{godot_types, string_name_ty, variant_ty};
17
17
18
18
use crate :: attribute_ops:: { FieldExportOps , PropertyOpts } ;
19
19
20
- #[ proc_macro_derive( GodotScript , attributes( export, script, prop) ) ]
20
+ #[ proc_macro_derive( GodotScript , attributes( export, script, prop, signal ) ) ]
21
21
pub fn derive ( input : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
22
22
let input = parse_macro_input ! ( input as DeriveInput ) ;
23
23
@@ -41,8 +41,13 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
41
41
|| field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "prop" ) )
42
42
} ) ;
43
43
44
+ let signal_fields = fields. iter ( ) . filter ( |field| {
45
+ field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "signal" ) )
46
+ } ) ;
47
+
44
48
let field_metadata_result: Result < TokenStream , TokenStream > = public_fields
45
49
. clone ( )
50
+ . filter ( |field| !field. attrs . iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "signal" ) ) )
46
51
. map ( |field| {
47
52
let name = field
48
53
. ident
@@ -64,23 +69,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
64
69
ops. hint ( field. ident . span ( ) ) ?
65
70
} ;
66
71
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) ;
84
73
let item = quote ! {
85
74
:: godot_rust_script:: RustScriptPropDesc {
86
75
name: #name,
@@ -101,7 +90,21 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
101
90
Err ( err) => return err. into ( ) ,
102
91
} ;
103
92
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) ) ;
105
108
let set_fields_impl = derive_set_fields ( public_fields. clone ( ) ) ;
106
109
let properties_state_impl = derive_property_states_export ( public_fields) ;
107
110
let default_impl = derive_default_with_base ( & fields) ;
@@ -122,7 +125,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
122
125
acc. extend ( lit) ;
123
126
acc
124
127
} ) ;
125
-
128
+
126
129
let output = quote ! {
127
130
impl :: godot_rust_script:: GodotScript for #script_type_ident {
128
131
#get_fields_impl
@@ -148,6 +151,9 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
148
151
concat!( #description) ,
149
152
vec![
150
153
#field_metadata
154
+ ] ,
155
+ vec![
156
+ #signal_metadata_result
151
157
]
152
158
) ;
153
159
@@ -205,8 +211,13 @@ fn derive_default_with_base(field_opts: &[FieldOpts]) -> TokenStream {
205
211
. iter ( )
206
212
. filter_map ( |field| match field. ident . as_ref ( ) {
207
213
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) ) , ) )
209
219
}
220
+
210
221
Some ( ident) => Some ( quote_spanned ! ( ident. span( ) => #ident: Default :: default ( ) , ) ) ,
211
222
None => None ,
212
223
} )
@@ -335,6 +346,25 @@ fn derive_property_states_export<'a>(
335
346
}
336
347
}
337
348
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
+
338
368
#[ proc_macro_attribute]
339
369
pub fn godot_script_impl (
340
370
args : proc_macro:: TokenStream ,
0 commit comments