@@ -13,7 +13,9 @@ use std::collections::BTreeMap;
1313use std:: collections:: btree_map:: Entry ;
1414use syn:: punctuated:: Punctuated ;
1515use syn:: spanned:: Spanned ;
16- use syn:: { Attribute , FnArg , Ident , ImplItem , ImplItemFn , LitStr , Pat , PatType , Token , Type } ;
16+ use syn:: {
17+ Attribute , FnArg , Ident , ImplItem , ImplItemFn , LitStr , Pat , PatIdent , PatType , Token , Type ,
18+ } ;
1719
1820#[ derive( Default ) ]
1921pub ( crate ) struct DBusItems {
@@ -52,9 +54,16 @@ pub(crate) enum DBusMethodArgumentProvider {
5254pub ( crate ) struct DBusSignal {
5355 pub ( crate ) item : ImplItemFn ,
5456 pub ( crate ) dbus_name : LitStr ,
57+ pub ( crate ) args : Vec < DBusSignalArgument > ,
5558 pub ( crate ) deprecated : bool ,
5659}
5760
61+ pub ( crate ) struct DBusSignalArgument {
62+ pub ( crate ) arg : PatType ,
63+ pub ( crate ) ident : Ident ,
64+ pub ( crate ) dbus_name : LitStr ,
65+ }
66+
5867pub ( crate ) fn parse_impl_items ( items : Vec < ImplItem > ) -> DBusItems {
5968 let mut output = DBusItems :: default ( ) ;
6069 for item in items {
@@ -71,13 +80,17 @@ pub(crate) fn parse_impl_items(items: Vec<ImplItem>) -> DBusItems {
7180 output. errors . push ( ( ImplItem :: Fn ( method. item ) , error) ) ;
7281 }
7382 }
74- DBusItem :: Signal ( dbus_signal) => {
75- let mut impl_item = ImplItem :: Fn ( dbus_signal. item ) ;
76- remove_dbus_attribute_from_impl_item ( & mut impl_item) ;
77- let span = impl_item. span ( ) ;
78- output
79- . errors
80- . push ( ( impl_item, syn:: Error :: new ( span, "[TODO]" ) ) ) ;
83+ DBusItem :: Signal ( mut signal) => {
84+ remove_dbus_attribute_from_item_fn ( & mut signal. item ) ;
85+ if let Entry :: Vacant ( entry) = output. signals . entry ( signal. dbus_name . value ( ) ) {
86+ entry. insert ( signal) ;
87+ } else {
88+ let error = syn:: Error :: new (
89+ signal. item . span ( ) ,
90+ "a signal with this name is already defined" ,
91+ ) ;
92+ output. errors . push ( ( ImplItem :: Fn ( signal. item ) , error) ) ;
93+ }
8194 }
8295 DBusItem :: Error ( mut impl_item, error) => {
8396 remove_dbus_attribute_from_impl_item ( & mut impl_item) ;
@@ -149,6 +162,12 @@ fn parse_impl_item_fn_for_signal(
149162 . name
150163 . unwrap_or_else ( || default_method_name ( & item. sig . ident ) ) ;
151164 let deprecated = is_deprecated ( & item. attrs ) ;
165+ let args = item
166+ . sig
167+ . inputs
168+ . iter ( )
169+ . filter_map ( |input| parse_signal_arg ( input. clone ( ) ) . transpose ( ) )
170+ . collect :: < Result < _ , _ > > ( ) ?;
152171
153172 if !item. block . stmts . is_empty ( ) {
154173 return Err ( syn:: Error :: new (
@@ -157,9 +176,17 @@ fn parse_impl_item_fn_for_signal(
157176 ) ) ;
158177 }
159178
179+ if matches ! ( item. sig. output, syn:: ReturnType :: Type ( ..) ) {
180+ return Err ( syn:: Error :: new (
181+ item. sig . output . span ( ) ,
182+ "signal must not specify a return type" ,
183+ ) ) ;
184+ }
185+
160186 Ok ( DBusSignal {
161187 item,
162188 dbus_name,
189+ args,
163190 deprecated,
164191 } )
165192}
@@ -187,6 +214,23 @@ fn parse_method_arg(
187214 } ) )
188215}
189216
217+ fn parse_signal_arg ( arg : FnArg ) -> syn:: Result < Option < DBusSignalArgument > > {
218+ let FnArg :: Typed ( typed) = arg else {
219+ return Ok ( None ) ;
220+ } ;
221+ let Pat :: Ident ( PatIdent { ident, .. } ) = typed. pat . as_ref ( ) else {
222+ return Err ( syn:: Error :: new (
223+ typed. pat . span ( ) ,
224+ "signal parameter must have a name" ,
225+ ) ) ;
226+ } ;
227+ Ok ( Some ( DBusSignalArgument {
228+ dbus_name : default_method_name ( ident) ,
229+ ident : ident. clone ( ) ,
230+ arg : typed,
231+ } ) )
232+ }
233+
190234fn is_deprecated ( attrs : & [ Attribute ] ) -> bool {
191235 attrs. iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "deprecated" ) )
192236}
0 commit comments