10
10
11
11
use super :: * ;
12
12
13
+ use hir;
14
+ use hir:: intravisit;
13
15
use hir:: def_id:: { CRATE_DEF_INDEX , DefId , DefIndex } ;
14
16
17
+ use middle:: cstore:: InlinedItem ;
18
+
15
19
use syntax:: ast:: * ;
16
20
use syntax:: visit;
17
21
18
22
/// Creates def ids for nodes in the HIR.
19
- pub struct DefCollector {
23
+ pub struct DefCollector < ' ast > {
24
+ // If we are walking HIR (c.f., AST), we need to keep a reference to the
25
+ // crate.
26
+ hir_crate : Option < & ' ast hir:: Crate > ,
20
27
pub definitions : Definitions ,
21
- pub parent_def : Option < DefIndex > ,
28
+ parent_def : Option < DefIndex > ,
22
29
}
23
30
24
- impl DefCollector {
25
- pub fn root ( ) -> DefCollector {
31
+ impl < ' ast > DefCollector < ' ast > {
32
+ pub fn root ( ) -> DefCollector < ' ast > {
26
33
let mut collector = DefCollector {
34
+ hir_crate : None ,
27
35
definitions : Definitions :: new ( ) ,
28
36
parent_def : None ,
29
37
} ;
@@ -39,8 +47,9 @@ impl DefCollector {
39
47
parent_def_path : DefPath ,
40
48
parent_def_id : DefId ,
41
49
definitions : Definitions )
42
- -> DefCollector {
50
+ -> DefCollector < ' ast > {
43
51
let mut collector = DefCollector {
52
+ hir_crate : None ,
44
53
parent_def : None ,
45
54
definitions : definitions,
46
55
} ;
@@ -57,6 +66,11 @@ impl DefCollector {
57
66
collector
58
67
}
59
68
69
+ pub fn walk_item ( & mut self , ii : & ' ast InlinedItem , krate : & ' ast hir:: Crate ) {
70
+ self . hir_crate = Some ( krate) ;
71
+ ii. visit ( self ) ;
72
+ }
73
+
60
74
fn parent_def ( & self ) -> Option < DefIndex > {
61
75
self . parent_def
62
76
}
@@ -83,7 +97,7 @@ impl DefCollector {
83
97
}
84
98
}
85
99
86
- impl < ' ast > visit:: Visitor < ' ast > for DefCollector {
100
+ impl < ' ast > visit:: Visitor < ' ast > for DefCollector < ' ast > {
87
101
fn visit_item ( & mut self , i : & ' ast Item ) {
88
102
debug ! ( "visit_item: {:?}" , i) ;
89
103
@@ -226,3 +240,151 @@ impl<'ast> visit::Visitor<'ast> for DefCollector {
226
240
self . create_def ( macro_def. id , DefPathData :: MacroDef ( macro_def. ident . name ) ) ;
227
241
}
228
242
}
243
+
244
+ // We walk the HIR rather than the AST when reading items from metadata.
245
+ impl < ' ast > intravisit:: Visitor < ' ast > for DefCollector < ' ast > {
246
+ /// Because we want to track parent items and so forth, enable
247
+ /// deep walking so that we walk nested items in the context of
248
+ /// their outer items.
249
+ fn visit_nested_item ( & mut self , item_id : hir:: ItemId ) {
250
+ debug ! ( "visit_nested_item: {:?}" , item_id) ;
251
+ let item = self . hir_crate . unwrap ( ) . item ( item_id. id ) ;
252
+ self . visit_item ( item)
253
+ }
254
+
255
+ fn visit_item ( & mut self , i : & ' ast hir:: Item ) {
256
+ debug ! ( "visit_item: {:?}" , i) ;
257
+
258
+ // Pick the def data. This need not be unique, but the more
259
+ // information we encapsulate into
260
+ let def_data = match i. node {
261
+ hir:: ItemDefaultImpl ( ..) | hir:: ItemImpl ( ..) =>
262
+ DefPathData :: Impl ,
263
+ hir:: ItemEnum ( ..) | hir:: ItemStruct ( ..) | hir:: ItemTrait ( ..) |
264
+ hir:: ItemExternCrate ( ..) | hir:: ItemMod ( ..) | hir:: ItemForeignMod ( ..) |
265
+ hir:: ItemTy ( ..) =>
266
+ DefPathData :: TypeNs ( i. name ) ,
267
+ hir:: ItemStatic ( ..) | hir:: ItemConst ( ..) | hir:: ItemFn ( ..) =>
268
+ DefPathData :: ValueNs ( i. name ) ,
269
+ hir:: ItemUse ( ..) => DefPathData :: Misc ,
270
+ } ;
271
+ let def = self . create_def ( i. id , def_data) ;
272
+
273
+ self . with_parent ( def, |this| {
274
+ match i. node {
275
+ hir:: ItemEnum ( ref enum_definition, _) => {
276
+ for v in & enum_definition. variants {
277
+ let variant_def_index =
278
+ this. create_def ( v. node . data . id ( ) ,
279
+ DefPathData :: EnumVariant ( v. node . name ) ) ;
280
+
281
+ for field in v. node . data . fields ( ) {
282
+ this. create_def_with_parent ( Some ( variant_def_index) ,
283
+ field. id ,
284
+ DefPathData :: Field ( field. name ) ) ;
285
+ }
286
+ }
287
+ }
288
+ hir:: ItemStruct ( ref struct_def, _) => {
289
+ // If this is a tuple-like struct, register the constructor.
290
+ if !struct_def. is_struct ( ) {
291
+ this. create_def ( struct_def. id ( ) ,
292
+ DefPathData :: StructCtor ) ;
293
+ }
294
+
295
+ for field in struct_def. fields ( ) {
296
+ this. create_def ( field. id , DefPathData :: Field ( field. name ) ) ;
297
+ }
298
+ }
299
+ _ => { }
300
+ }
301
+ intravisit:: walk_item ( this, i) ;
302
+ } ) ;
303
+ }
304
+
305
+ fn visit_foreign_item ( & mut self , foreign_item : & ' ast hir:: ForeignItem ) {
306
+ let def = self . create_def ( foreign_item. id , DefPathData :: ValueNs ( foreign_item. name ) ) ;
307
+
308
+ self . with_parent ( def, |this| {
309
+ intravisit:: walk_foreign_item ( this, foreign_item) ;
310
+ } ) ;
311
+ }
312
+
313
+ fn visit_generics ( & mut self , generics : & ' ast hir:: Generics ) {
314
+ for ty_param in generics. ty_params . iter ( ) {
315
+ self . create_def ( ty_param. id , DefPathData :: TypeParam ( ty_param. name ) ) ;
316
+ }
317
+
318
+ intravisit:: walk_generics ( self , generics) ;
319
+ }
320
+
321
+ fn visit_trait_item ( & mut self , ti : & ' ast hir:: TraitItem ) {
322
+ let def_data = match ti. node {
323
+ hir:: MethodTraitItem ( ..) | hir:: ConstTraitItem ( ..) =>
324
+ DefPathData :: ValueNs ( ti. name ) ,
325
+ hir:: TypeTraitItem ( ..) => DefPathData :: TypeNs ( ti. name ) ,
326
+ } ;
327
+
328
+ let def = self . create_def ( ti. id , def_data) ;
329
+ self . with_parent ( def, |this| {
330
+ if let hir:: ConstTraitItem ( _, Some ( ref expr) ) = ti. node {
331
+ this. create_def ( expr. id , DefPathData :: Initializer ) ;
332
+ }
333
+
334
+ intravisit:: walk_trait_item ( this, ti) ;
335
+ } ) ;
336
+ }
337
+
338
+ fn visit_impl_item ( & mut self , ii : & ' ast hir:: ImplItem ) {
339
+ let def_data = match ii. node {
340
+ hir:: ImplItemKind :: Method ( ..) | hir:: ImplItemKind :: Const ( ..) =>
341
+ DefPathData :: ValueNs ( ii. name ) ,
342
+ hir:: ImplItemKind :: Type ( ..) => DefPathData :: TypeNs ( ii. name ) ,
343
+ } ;
344
+
345
+ let def = self . create_def ( ii. id , def_data) ;
346
+ self . with_parent ( def, |this| {
347
+ if let hir:: ImplItemKind :: Const ( _, ref expr) = ii. node {
348
+ this. create_def ( expr. id , DefPathData :: Initializer ) ;
349
+ }
350
+
351
+ intravisit:: walk_impl_item ( this, ii) ;
352
+ } ) ;
353
+ }
354
+
355
+ fn visit_pat ( & mut self , pat : & ' ast hir:: Pat ) {
356
+ let maybe_binding = match pat. node {
357
+ hir:: PatKind :: Ident ( _, id, _) => Some ( id. node ) ,
358
+ _ => None
359
+ } ;
360
+
361
+ let parent_def = self . parent_def ;
362
+ if let Some ( id) = maybe_binding {
363
+ let def = self . create_def ( pat. id , DefPathData :: Binding ( id. name ) ) ;
364
+ self . parent_def = Some ( def) ;
365
+ }
366
+
367
+ intravisit:: walk_pat ( self , pat) ;
368
+ self . parent_def = parent_def;
369
+ }
370
+
371
+ fn visit_expr ( & mut self , expr : & ' ast hir:: Expr ) {
372
+ let parent_def = self . parent_def ;
373
+
374
+ if let hir:: ExprClosure ( ..) = expr. node {
375
+ let def = self . create_def ( expr. id , DefPathData :: ClosureExpr ) ;
376
+ self . parent_def = Some ( def) ;
377
+ }
378
+
379
+ intravisit:: walk_expr ( self , expr) ;
380
+ self . parent_def = parent_def;
381
+ }
382
+
383
+ fn visit_lifetime_def ( & mut self , def : & ' ast hir:: LifetimeDef ) {
384
+ self . create_def ( def. lifetime . id , DefPathData :: LifetimeDef ( def. lifetime . name ) ) ;
385
+ }
386
+
387
+ fn visit_macro_def ( & mut self , macro_def : & ' ast hir:: MacroDef ) {
388
+ self . create_def ( macro_def. id , DefPathData :: MacroDef ( macro_def. name ) ) ;
389
+ }
390
+ }
0 commit comments