@@ -4,10 +4,12 @@ use std::{
4
4
fmt:: { Display , Write } ,
5
5
fs:: read_dir,
6
6
path:: { PathBuf , MAIN_SEPARATOR as PATH_SEP } ,
7
+ sync:: Arc ,
7
8
} ;
8
9
9
10
use anyhow:: { Context , Result } ;
10
11
use glob:: glob;
12
+ use quote:: ToTokens ;
11
13
use syn:: {
12
14
parse_quote, Attribute , Ident , Item , ItemEnum , ItemFn , ItemImpl , ItemMacro , ItemMod ,
13
15
ItemStruct , ItemTrait , TraitItem , TraitItemMethod ,
@@ -98,9 +100,18 @@ pub fn generate_register() {
98
100
99
101
let out_file = out_dir. join ( filename) ;
100
102
101
- let mut queue = vec ! [ ( "" . to_string( ) , entry) ] ;
102
-
103
- while let Some ( ( mod_path, file_path) ) = queue. pop ( ) {
103
+ let mut queue = vec ! [ QueueEntry {
104
+ file_path: entry,
105
+ mod_path: "" . to_string( ) ,
106
+ attributes: Vec :: new( ) ,
107
+ } ] ;
108
+
109
+ while let Some ( QueueEntry {
110
+ file_path,
111
+ mod_path,
112
+ attributes,
113
+ } ) = queue. pop ( )
114
+ {
104
115
println ! ( "cargo:rerun-if-changed={}" , file_path. to_string_lossy( ) ) ;
105
116
let src = std:: fs:: read_to_string ( & file_path) . unwrap ( ) ;
106
117
@@ -110,6 +121,7 @@ pub fn generate_register() {
110
121
file_path : & file_path,
111
122
prefix : & prefix,
112
123
mod_path,
124
+ attributes,
113
125
114
126
register : & mut register_code,
115
127
values : & mut values,
@@ -120,24 +132,27 @@ pub fn generate_register() {
120
132
{
121
133
Ok ( file) => {
122
134
for item in file. items {
123
- ctx. process_item ( item) . unwrap ( ) ;
135
+ ctx. process_item ( & item) . unwrap ( ) ;
124
136
}
125
137
}
126
138
Err ( err) => println ! ( "{}" , err) ,
127
139
}
128
140
}
129
141
130
142
let mut values_code = String :: new ( ) ;
131
- for ( ( mod_path, ident) , ( global_name, trait_idents) ) in values {
143
+ for ( ( mod_path, ident) , entry) in values {
144
+ for attribute in & entry. attributes {
145
+ values_code. push_str ( attribute) ;
146
+ }
132
147
writeln ! (
133
148
values_code,
134
149
"crate{}::{}({}, #[allow(unused_variables)] |value| {{" ,
135
150
mod_path,
136
151
get_register_value_type_ident( & ident) ,
137
- global_name
152
+ entry . global_name,
138
153
)
139
154
. unwrap ( ) ;
140
- for trait_ident in trait_idents {
155
+ for trait_ident in entry . trait_idents {
141
156
writeln ! (
142
157
values_code,
143
158
" crate{}::{}(value);" ,
@@ -183,21 +198,36 @@ pub fn rerun_if_glob(globs: &str, root: &str) {
183
198
/// (mod_path, type_ident)
184
199
type ValueKey = ( String , Ident ) ;
185
200
/// (global_name, trait_register_fns)
186
- type ValueEntry = ( String , Vec < Ident > ) ;
201
+ struct ValueEntry {
202
+ attributes : Vec < Arc < String > > ,
203
+ global_name : String ,
204
+ trait_idents : Vec < Ident > ,
205
+ }
206
+
207
+ struct QueueEntry {
208
+ /// The on-disk path to the file representing this module.
209
+ file_path : PathBuf ,
210
+ /// The `syn::Path`-style representation of the module. Each component is
211
+ /// separated by `::`.
212
+ mod_path : String ,
213
+ /// Attributes (`#[cfg(...)]`) applied to the `ItemMod`.
214
+ attributes : Vec < Arc < String > > ,
215
+ }
187
216
188
217
struct RegisterContext < ' a > {
189
- queue : & ' a mut Vec < ( String , PathBuf ) > ,
218
+ queue : & ' a mut Vec < QueueEntry > ,
190
219
191
220
file_path : & ' a PathBuf ,
192
221
mod_path : String ,
222
+ attributes : Vec < Arc < String > > ,
193
223
prefix : & ' a str ,
194
224
195
225
register : & ' a mut String ,
196
226
values : & ' a mut HashMap < ValueKey , ValueEntry > ,
197
227
}
198
228
199
229
impl < ' a > RegisterContext < ' a > {
200
- fn process_item ( & mut self , item : Item ) -> Result < ( ) > {
230
+ fn process_item ( & mut self , item : & Item ) -> Result < ( ) > {
201
231
match item {
202
232
Item :: Enum ( enum_item) => self . process_enum ( enum_item) ,
203
233
Item :: Fn ( fn_item) => self . process_fn ( fn_item) ,
@@ -210,16 +240,24 @@ impl<'a> RegisterContext<'a> {
210
240
}
211
241
}
212
242
213
- fn process_enum ( & mut self , enum_item : ItemEnum ) -> Result < ( ) > {
214
- if has_attribute ( & enum_item. attrs , "value" ) {
243
+ fn process_enum ( & mut self , item : & ItemEnum ) -> Result < ( ) > {
244
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_enum_inner ( item) )
245
+ }
246
+
247
+ fn process_enum_inner ( & mut self , enum_item : & ItemEnum ) -> Result < ( ) > {
248
+ if has_turbo_attribute ( & enum_item. attrs , "value" ) {
215
249
self . add_value ( & enum_item. ident ) ;
216
250
self . add_value_debug_impl ( & enum_item. ident ) ;
217
251
}
218
252
Ok ( ( ) )
219
253
}
220
254
221
- fn process_fn ( & mut self , fn_item : ItemFn ) -> Result < ( ) > {
222
- if has_attribute ( & fn_item. attrs , "function" ) {
255
+ fn process_fn ( & mut self , item : & ItemFn ) -> Result < ( ) > {
256
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_fn_inner ( item) )
257
+ }
258
+
259
+ fn process_fn_inner ( & mut self , fn_item : & ItemFn ) -> Result < ( ) > {
260
+ if has_turbo_attribute ( & fn_item. attrs , "function" ) {
223
261
let ident = & fn_item. sig . ident ;
224
262
let type_ident = get_native_function_ident ( ident) ;
225
263
@@ -228,8 +266,12 @@ impl<'a> RegisterContext<'a> {
228
266
Ok ( ( ) )
229
267
}
230
268
231
- fn process_impl ( & mut self , impl_item : ItemImpl ) -> Result < ( ) > {
232
- if has_attribute ( & impl_item. attrs , "value_impl" ) {
269
+ fn process_impl ( & mut self , item : & ItemImpl ) -> Result < ( ) > {
270
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_impl_inner ( item) )
271
+ }
272
+
273
+ fn process_impl_inner ( & mut self , impl_item : & ItemImpl ) -> Result < ( ) > {
274
+ if has_turbo_attribute ( & impl_item. attrs , "value_impl" ) {
233
275
let struct_ident = get_type_ident ( & impl_item. self_ty ) . unwrap ( ) ;
234
276
235
277
let trait_ident = impl_item
@@ -241,7 +283,7 @@ impl<'a> RegisterContext<'a> {
241
283
self . add_value_trait ( & struct_ident, trait_ident) ;
242
284
}
243
285
244
- for item in impl_item. items {
286
+ for item in & impl_item. items {
245
287
if let syn:: ImplItem :: Method ( method_item) = item {
246
288
// TODO: if method_item.attrs.iter().any(|a|
247
289
// is_attribute(a,
@@ -266,46 +308,63 @@ impl<'a> RegisterContext<'a> {
266
308
Ok ( ( ) )
267
309
}
268
310
269
- fn process_mod ( & mut self , mod_item : ItemMod ) -> Result < ( ) > {
270
- if let Some ( ( _, items) ) = mod_item. content {
271
- let mod_name = mod_item. ident . to_string ( ) ;
272
- let child_mod_path = format ! ( "{}::{}" , self . mod_path, mod_name) ;
311
+ fn process_mod ( & mut self , item : & ItemMod ) -> Result < ( ) > {
312
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_mod_inner ( item) )
313
+ }
314
+
315
+ fn process_mod_inner ( & mut self , mod_item : & ItemMod ) -> Result < ( ) > {
316
+ let child_mod_name = mod_item. ident . to_string ( ) ;
317
+ let child_mod_path = format ! ( "{}::{}" , self . mod_path, child_mod_name) ;
318
+ if let Some ( ( _, items) ) = & mod_item. content {
273
319
let parent_mod_path = std:: mem:: replace ( & mut self . mod_path , child_mod_path) ;
274
320
for item in items {
275
321
self . process_item ( item) ?;
276
322
}
277
323
self . mod_path = parent_mod_path;
278
324
} else {
279
- let name = mod_item. ident . to_string ( ) ;
280
- let parent_path = self . file_path . parent ( ) . unwrap ( ) ;
281
- let direct = parent_path. join ( format ! ( "{name}.rs" ) ) ;
325
+ let parent_file_path = self . file_path . parent ( ) . unwrap ( ) ;
326
+ let direct = parent_file_path. join ( format ! ( "{child_mod_name}.rs" ) ) ;
282
327
if direct. exists ( ) {
283
- self . queue
284
- . push ( ( format ! ( "{}::{name}" , self . mod_path) , direct) ) ;
328
+ self . queue . push ( QueueEntry {
329
+ file_path : direct,
330
+ mod_path : child_mod_path,
331
+ attributes : self . attributes . clone ( ) ,
332
+ } ) ;
285
333
} else {
286
- let nested = parent_path . join ( & name ) . join ( "mod.rs" ) ;
334
+ let nested = parent_file_path . join ( & child_mod_name ) . join ( "mod.rs" ) ;
287
335
if nested. exists ( ) {
288
- self . queue
289
- . push ( ( format ! ( "{}::{name}" , self . mod_path) , nested) ) ;
336
+ self . queue . push ( QueueEntry {
337
+ file_path : nested,
338
+ mod_path : child_mod_path,
339
+ attributes : self . attributes . clone ( ) ,
340
+ } ) ;
290
341
}
291
342
}
292
343
}
293
344
Ok ( ( ) )
294
345
}
295
346
296
- fn process_struct ( & mut self , struct_item : ItemStruct ) -> Result < ( ) > {
297
- if has_attribute ( & struct_item. attrs , "value" ) {
347
+ fn process_struct ( & mut self , item : & ItemStruct ) -> Result < ( ) > {
348
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_struct_inner ( item) )
349
+ }
350
+
351
+ fn process_struct_inner ( & mut self , struct_item : & ItemStruct ) -> Result < ( ) > {
352
+ if has_turbo_attribute ( & struct_item. attrs , "value" ) {
298
353
self . add_value ( & struct_item. ident ) ;
299
354
self . add_value_debug_impl ( & struct_item. ident ) ;
300
355
}
301
356
Ok ( ( ) )
302
357
}
303
358
304
- fn process_trait ( & mut self , trait_item : ItemTrait ) -> Result < ( ) > {
359
+ fn process_trait ( & mut self , item : & ItemTrait ) -> Result < ( ) > {
360
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_trait_inner ( item) )
361
+ }
362
+
363
+ fn process_trait_inner ( & mut self , trait_item : & ItemTrait ) -> Result < ( ) > {
305
364
if let Some ( attr) = trait_item
306
365
. attrs
307
366
. iter ( )
308
- . find ( |a| is_attribute ( a, "value_trait" ) )
367
+ . find ( |a| is_turbo_attribute ( a, "value_trait" ) )
309
368
{
310
369
let trait_ident = & trait_item. ident ;
311
370
@@ -343,13 +402,17 @@ impl<'a> RegisterContext<'a> {
343
402
Ok ( ( ) )
344
403
}
345
404
346
- fn process_macro ( & mut self , macro_item : ItemMacro ) -> Result < ( ) > {
405
+ fn process_macro ( & mut self , item : & ItemMacro ) -> Result < ( ) > {
406
+ self . with_cfg_attrs ( & item. attrs , move |this| this. process_macro_inner ( item) )
407
+ }
408
+
409
+ fn process_macro_inner ( & mut self , macro_item : & ItemMacro ) -> Result < ( ) > {
347
410
if macro_item
348
411
. mac
349
412
. path
350
413
. is_ident ( "__turbo_tasks_internal_primitive" )
351
414
{
352
- let input = macro_item. mac . tokens ;
415
+ let input = macro_item. mac . tokens . clone ( ) ;
353
416
let input = syn:: parse2 :: < PrimitiveInput > ( input) . unwrap ( ) ;
354
417
355
418
let ty = input. ty ;
@@ -365,7 +428,7 @@ impl<'a> RegisterContext<'a> {
365
428
. path
366
429
. is_ident ( "__turbo_tasks_internal_generic_type" )
367
430
{
368
- let input = macro_item. mac . tokens ;
431
+ let input = macro_item. mac . tokens . clone ( ) ;
369
432
let input = syn:: parse2 :: < GenericTypeInput > ( input) . unwrap ( ) ;
370
433
371
434
let ty = input. ty ;
@@ -398,7 +461,11 @@ impl<'a> RegisterContext<'a> {
398
461
399
462
fn add_value ( & mut self , ident : & Ident ) {
400
463
let key: ValueKey = ( self . mod_path . clone ( ) , ident. clone ( ) ) ;
401
- let value: ValueEntry = ( self . get_global_name ( & [ ident] ) , Vec :: new ( ) ) ;
464
+ let value = ValueEntry {
465
+ attributes : self . attributes . clone ( ) ,
466
+ global_name : self . get_global_name ( & [ ident] ) ,
467
+ trait_idents : Vec :: new ( ) ,
468
+ } ;
402
469
403
470
assert ! (
404
471
self . values. insert( key, value) . is_none( ) ,
@@ -444,14 +511,17 @@ impl<'a> RegisterContext<'a> {
444
511
self . file_path. display( )
445
512
) ;
446
513
}
447
- entry. unwrap ( ) . 1 . push ( trait_ident. clone ( ) ) ;
514
+ entry. unwrap ( ) . trait_idents . push ( trait_ident. clone ( ) ) ;
448
515
}
449
516
450
517
fn register (
451
518
& mut self ,
452
519
type_ident : impl Display ,
453
520
global_name : impl Display ,
454
521
) -> std:: fmt:: Result {
522
+ for attribute in & self . attributes {
523
+ self . register . push_str ( attribute) ;
524
+ }
455
525
writeln ! (
456
526
self . register,
457
527
"crate{}::{}.register({});" ,
@@ -503,13 +573,24 @@ impl<'a> RegisterContext<'a> {
503
573
& [ "value_default" ] ,
504
574
)
505
575
}
576
+
577
+ fn with_cfg_attrs < T > ( & mut self , attrs : & [ Attribute ] , func : impl FnOnce ( & mut Self ) -> T ) -> T {
578
+ let orig_len = self . attributes . len ( ) ;
579
+ for attr in attrs. iter ( ) . filter ( |a| is_cfg_attribute ( a) ) {
580
+ self . attributes
581
+ . push ( Arc :: new ( attr. to_token_stream ( ) . to_string ( ) ) ) ;
582
+ }
583
+ let ret = func ( self ) ;
584
+ self . attributes . truncate ( orig_len) ;
585
+ ret
586
+ }
506
587
}
507
588
508
- fn has_attribute ( attrs : & [ Attribute ] , name : & str ) -> bool {
509
- attrs. iter ( ) . any ( |a| is_attribute ( a, name) )
589
+ fn has_turbo_attribute ( attrs : & [ Attribute ] , name : & str ) -> bool {
590
+ attrs. iter ( ) . any ( |a| is_turbo_attribute ( a, name) )
510
591
}
511
592
512
- fn is_attribute ( attr : & Attribute , name : & str ) -> bool {
593
+ fn is_turbo_attribute ( attr : & Attribute , name : & str ) -> bool {
513
594
let path = & attr. path ;
514
595
if path. leading_colon . is_some ( ) {
515
596
return false ;
@@ -524,6 +605,12 @@ fn is_attribute(attr: &Attribute, name: &str) -> bool {
524
605
}
525
606
}
526
607
608
+ fn is_cfg_attribute ( attr : & Attribute ) -> bool {
609
+ attr. path
610
+ . get_ident ( )
611
+ . is_some_and ( |ident| ident == "cfg" || ident == "cfg_attr" )
612
+ }
613
+
527
614
fn parse_attr_args < T > ( attr : & Attribute ) -> syn:: Result < Option < T > >
528
615
where
529
616
T : syn:: parse:: Parse ,
0 commit comments