2
2
3
3
use std:: sync:: Arc ;
4
4
5
- use hir_expand:: { name:: Name , AstId , ExpandResult , InFile } ;
5
+ use hir_expand:: { name:: Name , AstId , ExpandResult , InFile , MacroCallId } ;
6
6
use syntax:: ast;
7
7
8
8
use crate :: {
@@ -184,6 +184,8 @@ pub struct TraitData {
184
184
/// method calls to this trait's methods when the receiver is an array and the crate edition is
185
185
/// 2015 or 2018.
186
186
pub skip_array_during_method_dispatch : bool ,
187
+ // box it as the vec is usually empty anyways
188
+ pub attribute_calls : Option < Box < Vec < ( AstId < ast:: Item > , MacroCallId ) > > > ,
187
189
}
188
190
189
191
impl TraitData {
@@ -207,15 +209,8 @@ impl TraitData {
207
209
. by_key ( "rustc_skip_array_during_method_dispatch" )
208
210
. exists ( ) ;
209
211
210
- let items = collect_items (
211
- db,
212
- module_id,
213
- & mut expander,
214
- tr_def. items . iter ( ) . copied ( ) ,
215
- tr_loc. id . tree_id ( ) ,
216
- container,
217
- 100 ,
218
- ) ;
212
+ let ( items, attribute_calls) =
213
+ do_collect ( db, module_id, & mut expander, & tr_def. items , tr_loc. id . tree_id ( ) , container) ;
219
214
220
215
Arc :: new ( TraitData {
221
216
name,
@@ -224,6 +219,7 @@ impl TraitData {
224
219
is_unsafe,
225
220
visibility,
226
221
skip_array_during_method_dispatch,
222
+ attribute_calls,
227
223
} )
228
224
}
229
225
@@ -247,6 +243,10 @@ impl TraitData {
247
243
_ => None ,
248
244
} )
249
245
}
246
+
247
+ pub fn attribute_calls ( & self ) -> impl Iterator < Item = ( AstId < ast:: Item > , MacroCallId ) > + ' _ {
248
+ self . attribute_calls . iter ( ) . flat_map ( |it| it. iter ( ) ) . copied ( )
249
+ }
250
250
}
251
251
252
252
#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -255,6 +255,8 @@ pub struct ImplData {
255
255
pub self_ty : Interned < TypeRef > ,
256
256
pub items : Vec < AssocItemId > ,
257
257
pub is_negative : bool ,
258
+ // box it as the vec is usually empty anyways
259
+ pub attribute_calls : Option < Box < Vec < ( AstId < ast:: Item > , MacroCallId ) > > > ,
258
260
}
259
261
260
262
impl ImplData {
@@ -271,18 +273,21 @@ impl ImplData {
271
273
let container = ItemContainerId :: ImplId ( id) ;
272
274
let mut expander = Expander :: new ( db, impl_loc. id . file_id ( ) , module_id) ;
273
275
274
- let items = collect_items (
276
+ let ( items, attribute_calls ) = do_collect (
275
277
db,
276
278
module_id,
277
279
& mut expander,
278
- impl_def. items . iter ( ) . copied ( ) ,
280
+ & impl_def. items ,
279
281
impl_loc. id . tree_id ( ) ,
280
282
container,
281
- 100 ,
282
283
) ;
283
284
let items = items. into_iter ( ) . map ( |( _, item) | item) . collect ( ) ;
284
285
285
- Arc :: new ( ImplData { target_trait, self_ty, items, is_negative } )
286
+ Arc :: new ( ImplData { target_trait, self_ty, items, is_negative, attribute_calls } )
287
+ }
288
+
289
+ pub fn attribute_calls ( & self ) -> impl Iterator < Item = ( AstId < ast:: Item > , MacroCallId ) > + ' _ {
290
+ self . attribute_calls . iter ( ) . flat_map ( |it| it. iter ( ) ) . copied ( )
286
291
}
287
292
}
288
293
@@ -333,41 +338,70 @@ impl StaticData {
333
338
}
334
339
}
335
340
341
+ fn do_collect (
342
+ db : & dyn DefDatabase ,
343
+ module_id : ModuleId ,
344
+ expander : & mut Expander ,
345
+ assoc_items : & [ AssocItem ] ,
346
+ tree_id : item_tree:: TreeId ,
347
+ container : ItemContainerId ,
348
+ ) -> ( Vec < ( Name , AssocItemId ) > , Option < Box < Vec < ( AstId < ast:: Item > , MacroCallId ) > > > ) {
349
+ let mut items = Vec :: new ( ) ;
350
+ let mut attribute_calls = Vec :: new ( ) ;
351
+
352
+ collect_items (
353
+ db,
354
+ & mut items,
355
+ & mut attribute_calls,
356
+ module_id,
357
+ expander,
358
+ assoc_items. iter ( ) . copied ( ) ,
359
+ tree_id,
360
+ container,
361
+ 100 ,
362
+ ) ;
363
+
364
+ let attribute_calls =
365
+ if attribute_calls. is_empty ( ) { None } else { Some ( Box :: new ( attribute_calls) ) } ;
366
+ ( items, attribute_calls)
367
+ }
368
+
336
369
fn collect_items (
337
370
db : & dyn DefDatabase ,
371
+ items : & mut Vec < ( Name , AssocItemId ) > ,
372
+ attr_calls : & mut Vec < ( AstId < ast:: Item > , MacroCallId ) > ,
338
373
module : ModuleId ,
339
374
expander : & mut Expander ,
340
375
assoc_items : impl Iterator < Item = AssocItem > ,
341
376
tree_id : item_tree:: TreeId ,
342
377
container : ItemContainerId ,
343
378
limit : usize ,
344
- ) -> Vec < ( Name , AssocItemId ) > {
379
+ ) {
345
380
if limit == 0 {
346
- return Vec :: new ( ) ;
381
+ return ;
347
382
}
348
383
349
384
let item_tree = tree_id. item_tree ( db) ;
350
385
let crate_graph = db. crate_graph ( ) ;
351
386
let cfg_options = & crate_graph[ module. krate ] . cfg_options ;
352
387
let def_map = module. def_map ( db) ;
353
388
354
- let mut items = Vec :: new ( ) ;
355
389
' items: for item in assoc_items {
356
390
let attrs = item_tree. attrs ( db, module. krate , ModItem :: from ( item) . into ( ) ) ;
357
391
if !attrs. is_cfg_enabled ( cfg_options) {
358
392
continue ;
359
393
}
360
394
361
395
for attr in & * attrs {
362
- let ast_id = AstIdWithPath {
363
- path : ( * attr. path ) . clone ( ) ,
364
- ast_id : AstId :: new ( expander. current_file_id ( ) , item. ast_id ( & item_tree) . upcast ( ) ) ,
365
- } ;
396
+ let ast_id = AstId :: new ( expander. current_file_id ( ) , item. ast_id ( & item_tree) . upcast ( ) ) ;
397
+ let ast_id_with_path = AstIdWithPath { path : ( * attr. path ) . clone ( ) , ast_id } ;
398
+
366
399
if let Ok ( ResolvedAttr :: Macro ( call_id) ) =
367
- def_map. resolve_attr_macro ( db, module. local_id , ast_id , attr)
400
+ def_map. resolve_attr_macro ( db, module. local_id , ast_id_with_path , attr)
368
401
{
402
+ attr_calls. push ( ( ast_id, call_id) ) ;
369
403
let res = expander. enter_expand_id ( db, call_id) ;
370
- items . extend ( collect_macro_items ( db, module, expander, container, limit, res) ) ;
404
+ collect_macro_items ( db, items , attr_calls , module, expander, container, limit, res) ;
371
405
continue ' items;
372
406
}
373
407
}
@@ -401,34 +435,32 @@ fn collect_items(
401
435
let res = expander. enter_expand ( db, call) ;
402
436
403
437
if let Ok ( res) = res {
404
- items. extend ( collect_macro_items ( db, module, expander, container, limit, res) ) ;
438
+ collect_macro_items (
439
+ db, items, attr_calls, module, expander, container, limit, res,
440
+ ) ;
405
441
}
406
442
}
407
443
}
408
444
}
409
-
410
- items
411
445
}
412
446
413
447
fn collect_macro_items (
414
448
db : & dyn DefDatabase ,
449
+ items : & mut Vec < ( Name , AssocItemId ) > ,
450
+ attr_calls : & mut Vec < ( AstId < ast:: Item > , MacroCallId ) > ,
415
451
module : ModuleId ,
416
452
expander : & mut Expander ,
417
453
container : ItemContainerId ,
418
454
limit : usize ,
419
455
res : ExpandResult < Option < ( Mark , ast:: MacroItems ) > > ,
420
- ) -> Vec < ( Name , AssocItemId ) > {
456
+ ) {
421
457
if let Some ( ( mark, mac) ) = res. value {
422
458
let src: InFile < ast:: MacroItems > = expander. to_source ( mac) ;
423
459
let tree_id = item_tree:: TreeId :: new ( src. file_id , None ) ;
424
460
let item_tree = tree_id. item_tree ( db) ;
425
461
let iter = item_tree. top_level_items ( ) . iter ( ) . filter_map ( ModItem :: as_assoc_item) ;
426
- let items = collect_items ( db, module, expander, iter, tree_id, container, limit - 1 ) ;
462
+ collect_items ( db, items , attr_calls , module, expander, iter, tree_id, container, limit - 1 ) ;
427
463
428
464
expander. exit ( db, mark) ;
429
-
430
- return items;
431
465
}
432
-
433
- Vec :: new ( )
434
466
}
0 commit comments