@@ -4,21 +4,101 @@ use proc_macro2::TokenStream;
4
4
use proc_macro_error:: abort_call_site;
5
5
use quote:: { quote, ToTokens } ;
6
6
7
- pub const WRONG_EXPRESSION_MSG : & str =
8
- "This macro's attributes should be a sequence of assign expressions punctuated by comma" ;
9
-
10
- pub const UNSUPPORTED_EXPRESSION_MSG : & str =
11
- "This macro's supported attributes are: `plugin_type = <subclass_of_glib::TypePlugin>, lazy_registration = true|false`" ;
7
+ use crate :: utils:: { parse_optional_nested_meta_items, NestedMetaItem } ;
12
8
13
9
pub const WRONG_PLACE_MSG : & str =
14
10
"This macro should be used on `impl` block for `glib::ObjectInterface` trait" ;
15
11
16
- pub fn impl_object_interface ( input : & syn:: ItemImpl ) -> TokenStream {
12
+ pub fn impl_object_interface ( input : & mut syn:: ItemImpl ) -> TokenStream {
17
13
let crate_ident = crate :: utils:: crate_ident_new ( ) ;
18
- let syn:: ItemImpl { self_ty, .. } = & input;
14
+ let syn:: ItemImpl {
15
+ attrs,
16
+ generics,
17
+ trait_,
18
+ self_ty,
19
+ unsafety,
20
+ items,
21
+ ..
22
+ } = input;
23
+
24
+ let mut plugin_type = NestedMetaItem :: < syn:: Path > :: new ( "plugin_type" ) . value_required ( ) ;
25
+ let mut lazy_registration =
26
+ NestedMetaItem :: < syn:: LitBool > :: new ( "lazy_registration" ) . value_required ( ) ;
27
+
28
+ let found = parse_optional_nested_meta_items (
29
+ & * attrs,
30
+ "object_interface_dynamic" ,
31
+ & mut [ & mut plugin_type, & mut lazy_registration] ,
32
+ ) ;
33
+
34
+ let register_object_interface = match found {
35
+ Err ( e) => return e. to_compile_error ( ) ,
36
+ Ok ( None ) => register_object_interface_as_static ( & crate_ident, self_ty) ,
37
+ Ok ( Some ( _) ) => {
38
+ // remove attribute 'object_interface_dynamic' from the attribute list because it is not a real proc_macro_attribute
39
+ attrs. retain ( |attr| !attr. path ( ) . is_ident ( "object_interface_dynamic" ) ) ;
40
+ let plugin_ty = plugin_type
41
+ . value
42
+ . map ( |p| p. into_token_stream ( ) )
43
+ . unwrap_or ( quote ! ( #crate_ident:: TypeModule ) ) ;
44
+ let lazy_registration = lazy_registration. value . map ( |b| b. value ) . unwrap_or_default ( ) ;
45
+ register_object_interface_as_dynamic (
46
+ & crate_ident,
47
+ self_ty,
48
+ plugin_ty,
49
+ lazy_registration,
50
+ )
51
+ }
52
+ } ;
53
+
54
+ let mut has_prerequisites = false ;
55
+ for item in items. iter ( ) {
56
+ if let syn:: ImplItem :: Type ( type_) = item {
57
+ let name = type_. ident . to_string ( ) ;
58
+ if name == "Prerequisites" {
59
+ has_prerequisites = true ;
60
+ }
61
+ }
62
+ }
63
+
64
+ let prerequisites_opt = if has_prerequisites {
65
+ None
66
+ } else {
67
+ Some ( quote ! (
68
+ type Prerequisites = ( ) ;
69
+ ) )
70
+ } ;
71
+
72
+ let trait_path = match & trait_ {
73
+ Some ( path) => & path. 1 ,
74
+ None => abort_call_site ! ( WRONG_PLACE_MSG ) ,
75
+ } ;
19
76
77
+ quote ! {
78
+ #( #attrs) *
79
+ #unsafety impl #generics #trait_path for #self_ty {
80
+ #prerequisites_opt
81
+ #( #items) *
82
+ }
83
+
84
+ unsafe impl #crate_ident:: subclass:: interface:: ObjectInterfaceType for #self_ty {
85
+ #[ inline]
86
+ fn type_( ) -> #crate_ident:: Type {
87
+ Self :: register_interface( )
88
+ }
89
+ }
90
+
91
+ #register_object_interface
92
+ }
93
+ }
94
+
95
+ // Registers the object interface as a static type.
96
+ fn register_object_interface_as_static (
97
+ crate_ident : & TokenStream ,
98
+ self_ty : & syn:: Type ,
99
+ ) -> TokenStream {
20
100
// registers the interface on first use (lazy registration).
21
- let register_interface = quote ! {
101
+ quote ! {
22
102
impl #self_ty {
23
103
/// Registers the interface only once.
24
104
#[ inline]
@@ -35,60 +115,20 @@ pub fn impl_object_interface(input: &syn::ItemImpl) -> TokenStream {
35
115
}
36
116
}
37
117
}
38
- } ;
39
-
40
- impl_object_interface_ ( register_interface, input)
118
+ }
41
119
}
42
120
43
- pub fn impl_dynamic_object_interface (
44
- attrs : & syn:: punctuated:: Punctuated < syn:: Expr , syn:: Token ![ , ] > ,
45
- input : & syn:: ItemImpl ,
121
+ // The following implementations follows the lifecycle of plugins and of dynamic types (see [`TypePluginExt`] and [`TypeModuleExt`]).
122
+ // An object interface can be reregistered as a dynamic type.
123
+ fn register_object_interface_as_dynamic (
124
+ crate_ident : & TokenStream ,
125
+ self_ty : & syn:: Type ,
126
+ plugin_ty : TokenStream ,
127
+ lazy_registration : bool ,
46
128
) -> TokenStream {
47
- let crate_ident = crate :: utils:: crate_ident_new ( ) ;
48
- let syn:: ItemImpl { self_ty, .. } = & input;
49
-
50
- let mut plugin_type_opt: Option < syn:: Path > = None ;
51
- let mut lazy_registration_opt: Option < bool > = None ;
52
-
53
- for attr in attrs {
54
- match attr {
55
- // attribute must be one of supported assign expressions.
56
- syn:: Expr :: Assign ( syn:: ExprAssign { left, right, .. } ) => {
57
- match ( * left. to_owned ( ) , * right. to_owned ( ) ) {
58
- // `plugin_type = <subclass_of_TypePlugin>`
59
- (
60
- syn:: Expr :: Path ( syn:: ExprPath { path : path1, .. } ) ,
61
- syn:: Expr :: Path ( syn:: ExprPath { path : path2, .. } ) ,
62
- ) if path1. is_ident ( & "plugin_type" ) => plugin_type_opt = Some ( path2) ,
63
- // `lazy_registration = true|false`
64
- (
65
- syn:: Expr :: Path ( syn:: ExprPath { path, .. } ) ,
66
- syn:: Expr :: Lit ( syn:: ExprLit {
67
- lit : syn:: Lit :: Bool ( syn:: LitBool { value, .. } ) ,
68
- ..
69
- } ) ,
70
- ) if path. is_ident ( & "lazy_registration" ) => lazy_registration_opt = Some ( value) ,
71
- _ => abort_call_site ! ( UNSUPPORTED_EXPRESSION_MSG ) ,
72
- } ;
73
- }
74
- _ => abort_call_site ! ( WRONG_EXPRESSION_MSG ) ,
75
- } ;
76
- }
77
-
78
- let ( plugin_ty, lazy_registration) = match ( plugin_type_opt, lazy_registration_opt) {
79
- ( Some ( type_plugin) , lazy_registration_opt) => (
80
- type_plugin. into_token_stream ( ) ,
81
- lazy_registration_opt. unwrap_or_default ( ) ,
82
- ) ,
83
- ( None , lazy_registration_opt) => (
84
- quote ! ( #crate_ident:: TypeModule ) ,
85
- lazy_registration_opt. unwrap_or_default ( ) ,
86
- ) ,
87
- } ;
88
-
89
129
// The following implementations follows the lifecycle of plugins and of dynamic types (see [`TypePluginExt`] and [`TypeModuleExt`]).
90
130
// An object interface can be reregistered as a dynamic type.
91
- let register_interface = if lazy_registration {
131
+ if lazy_registration {
92
132
// registers the object interface as a dynamic type on the first use (lazy registration).
93
133
// a weak reference on the plugin is stored and will be used later on the first use of the object interface.
94
134
// this implementation relies on a static storage of a weak reference on the plugin and of the GLib type to know if the object interface has been registered.
@@ -201,64 +241,5 @@ pub fn impl_dynamic_object_interface(
201
241
}
202
242
}
203
243
}
204
- } ;
205
-
206
- impl_object_interface_ ( register_interface, input)
207
- }
208
-
209
- pub fn impl_object_interface_ (
210
- register_interface : TokenStream ,
211
- input : & syn:: ItemImpl ,
212
- ) -> TokenStream {
213
- let mut has_prerequisites = false ;
214
- for item in & input. items {
215
- if let syn:: ImplItem :: Type ( type_) = item {
216
- let name = type_. ident . to_string ( ) ;
217
- if name == "Prerequisites" {
218
- has_prerequisites = true ;
219
- }
220
- }
221
- }
222
-
223
- let syn:: ItemImpl {
224
- attrs,
225
- generics,
226
- trait_,
227
- self_ty,
228
- unsafety,
229
- items,
230
- ..
231
- } = & input;
232
-
233
- let prerequisites_opt = if has_prerequisites {
234
- None
235
- } else {
236
- Some ( quote ! (
237
- type Prerequisites = ( ) ;
238
- ) )
239
- } ;
240
-
241
- let crate_ident = crate :: utils:: crate_ident_new ( ) ;
242
-
243
- let trait_path = match & trait_ {
244
- Some ( path) => & path. 1 ,
245
- None => abort_call_site ! ( WRONG_PLACE_MSG ) ,
246
- } ;
247
-
248
- quote ! {
249
- #( #attrs) *
250
- #unsafety impl #generics #trait_path for #self_ty {
251
- #prerequisites_opt
252
- #( #items) *
253
- }
254
-
255
- unsafe impl #crate_ident:: subclass:: interface:: ObjectInterfaceType for #self_ty {
256
- #[ inline]
257
- fn type_( ) -> #crate_ident:: Type {
258
- Self :: register_interface( )
259
- }
260
- }
261
-
262
- #register_interface
263
244
}
264
245
}
0 commit comments