@@ -5,10 +5,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5
5
use rustc_hir as hir;
6
6
use rustc_hir:: def:: { DefKind , Res } ;
7
7
use rustc_hir:: def_id:: DefId ;
8
- use rustc_hir:: intravisit:: { walk_item, Visitor } ;
9
8
use rustc_hir:: Node ;
10
9
use rustc_hir:: CRATE_HIR_ID ;
11
- use rustc_middle:: hir:: nested_filter;
12
10
use rustc_middle:: ty:: TyCtxt ;
13
11
use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
14
12
use rustc_span:: symbol:: { kw, sym, Symbol } ;
@@ -59,34 +57,29 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool
59
57
false
60
58
}
61
59
60
+ // Also, is there some reason that this doesn't use the 'visit'
61
+ // framework from syntax?.
62
+
62
63
pub ( crate ) struct RustdocVisitor < ' a , ' tcx > {
63
64
cx : & ' a mut core:: DocContext < ' tcx > ,
64
65
view_item_stack : FxHashSet < hir:: HirId > ,
65
66
inlining : bool ,
66
67
/// Are the current module and all of its parents public?
67
68
inside_public_path : bool ,
68
69
exact_paths : FxHashMap < DefId , Vec < Symbol > > ,
69
- modules : Vec < Module < ' tcx > > ,
70
70
}
71
71
72
72
impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
73
73
pub ( crate ) fn new ( cx : & ' a mut core:: DocContext < ' tcx > ) -> RustdocVisitor < ' a , ' tcx > {
74
74
// If the root is re-exported, terminate all recursion.
75
75
let mut stack = FxHashSet :: default ( ) ;
76
76
stack. insert ( hir:: CRATE_HIR_ID ) ;
77
- let om = Module :: new (
78
- cx. tcx . crate_name ( LOCAL_CRATE ) ,
79
- hir:: CRATE_HIR_ID ,
80
- cx. tcx . hir ( ) . root_module ( ) . spans . inner_span ,
81
- ) ;
82
-
83
77
RustdocVisitor {
84
78
cx,
85
79
view_item_stack : stack,
86
80
inlining : false ,
87
81
inside_public_path : true ,
88
82
exact_paths : FxHashMap :: default ( ) ,
89
- modules : vec ! [ om] ,
90
83
}
91
84
}
92
85
@@ -96,10 +89,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
96
89
}
97
90
98
91
pub ( crate ) fn visit ( mut self ) -> Module < ' tcx > {
99
- let root_module = self . cx . tcx . hir ( ) . root_module ( ) ;
100
- self . visit_mod_contents ( CRATE_HIR_ID , root_module) ;
101
-
102
- let mut top_level_module = self . modules . pop ( ) . unwrap ( ) ;
92
+ let mut top_level_module = self . visit_mod_contents (
93
+ hir:: CRATE_HIR_ID ,
94
+ self . cx . tcx . hir ( ) . root_module ( ) ,
95
+ self . cx . tcx . crate_name ( LOCAL_CRATE ) ,
96
+ None ,
97
+ ) ;
103
98
104
99
// `#[macro_export] macro_rules!` items are reexported at the top level of the
105
100
// crate, regardless of where they're defined. We want to document the
@@ -114,13 +109,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
114
109
// macro in the same module.
115
110
let mut inserted = FxHashSet :: default ( ) ;
116
111
for export in self . cx . tcx . module_reexports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
117
- if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res &&
118
- let Some ( local_def_id) = def_id. as_local ( ) &&
119
- self . cx . tcx . has_attr ( def_id, sym:: macro_export) &&
120
- inserted. insert ( def_id)
121
- {
122
- let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
123
- top_level_module. items . push ( ( item, None , None ) ) ;
112
+ if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res {
113
+ if let Some ( local_def_id) = def_id. as_local ( ) {
114
+ if self . cx . tcx . has_attr ( def_id, sym:: macro_export) {
115
+ if inserted. insert ( def_id) {
116
+ let item = self . cx . tcx . hir ( ) . expect_item ( local_def_id) ;
117
+ top_level_module. items . push ( ( item, None , None ) ) ;
118
+ }
119
+ }
120
+ }
124
121
}
125
122
}
126
123
@@ -154,34 +151,36 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
154
151
top_level_module
155
152
}
156
153
157
- /// This method will go through the given module items in two passes:
158
- /// 1. The items which are not glob imports/reexports.
159
- /// 2. The glob imports/reexports.
160
- fn visit_mod_contents ( & mut self , id : hir:: HirId , m : & ' tcx hir:: Mod < ' tcx > ) {
161
- debug ! ( "Going through module {:?}" , m) ;
154
+ fn visit_mod_contents (
155
+ & mut self ,
156
+ id : hir:: HirId ,
157
+ m : & ' tcx hir:: Mod < ' tcx > ,
158
+ name : Symbol ,
159
+ parent_id : Option < hir:: HirId > ,
160
+ ) -> Module < ' tcx > {
161
+ let mut om = Module :: new ( name, id, m. spans . inner_span ) ;
162
162
let def_id = self . cx . tcx . hir ( ) . local_def_id ( id) . to_def_id ( ) ;
163
163
// Keep track of if there were any private modules in the path.
164
164
let orig_inside_public_path = self . inside_public_path ;
165
165
self . inside_public_path &= self . cx . tcx . visibility ( def_id) . is_public ( ) ;
166
-
167
- // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
168
- // the second loop):
169
166
for & i in m. item_ids {
170
167
let item = self . cx . tcx . hir ( ) . item ( i) ;
171
- if ! matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
172
- self . visit_item ( item ) ;
168
+ if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
169
+ continue ;
173
170
}
171
+ self . visit_item ( item, None , & mut om, parent_id) ;
174
172
}
175
173
for & i in m. item_ids {
176
174
let item = self . cx . tcx . hir ( ) . item ( i) ;
177
175
// To match the way import precedence works, visit glob imports last.
178
176
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
179
177
// imported items appear last, then they'll be the ones that get discarded.
180
178
if matches ! ( item. kind, hir:: ItemKind :: Use ( _, hir:: UseKind :: Glob ) ) {
181
- self . visit_item ( item) ;
179
+ self . visit_item ( item, None , & mut om , parent_id ) ;
182
180
}
183
181
}
184
182
self . inside_public_path = orig_inside_public_path;
183
+ om
185
184
}
186
185
187
186
/// Tries to resolve the target of a `pub use` statement and inlines the
@@ -199,6 +198,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
199
198
res : Res ,
200
199
renamed : Option < Symbol > ,
201
200
glob : bool ,
201
+ om : & mut Module < ' tcx > ,
202
202
please_inline : bool ,
203
203
) -> bool {
204
204
debug ! ( "maybe_inline_local res: {:?}" , res) ;
@@ -249,20 +249,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
249
249
let prev = mem:: replace ( & mut self . inlining , true ) ;
250
250
for & i in m. item_ids {
251
251
let i = self . cx . tcx . hir ( ) . item ( i) ;
252
- self . visit_item_inner ( i, None , Some ( id) ) ;
252
+ self . visit_item ( i, None , om , Some ( id) ) ;
253
253
}
254
254
self . inlining = prev;
255
255
true
256
256
}
257
257
Node :: Item ( it) if !glob => {
258
258
let prev = mem:: replace ( & mut self . inlining , true ) ;
259
- self . visit_item_inner ( it, renamed, Some ( id) ) ;
259
+ self . visit_item ( it, renamed, om , Some ( id) ) ;
260
260
self . inlining = prev;
261
261
true
262
262
}
263
263
Node :: ForeignItem ( it) if !glob => {
264
264
let prev = mem:: replace ( & mut self . inlining , true ) ;
265
- self . visit_foreign_item_inner ( it, renamed) ;
265
+ self . visit_foreign_item ( it, renamed, om ) ;
266
266
self . inlining = prev;
267
267
true
268
268
}
@@ -272,22 +272,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
272
272
ret
273
273
}
274
274
275
- #[ inline]
276
- fn add_to_current_mod (
275
+ fn visit_item (
277
276
& mut self ,
278
277
item : & ' tcx hir:: Item < ' _ > ,
279
278
renamed : Option < Symbol > ,
279
+ om : & mut Module < ' tcx > ,
280
280
parent_id : Option < hir:: HirId > ,
281
281
) {
282
- self . modules . last_mut ( ) . unwrap ( ) . items . push ( ( item, renamed, parent_id) )
283
- }
284
-
285
- fn visit_item_inner (
286
- & mut self ,
287
- item : & ' tcx hir:: Item < ' _ > ,
288
- renamed : Option < Symbol > ,
289
- parent_id : Option < hir:: HirId > ,
290
- ) -> bool {
291
282
debug ! ( "visiting item {:?}" , item) ;
292
283
let name = renamed. unwrap_or ( item. ident . name ) ;
293
284
@@ -302,7 +293,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
302
293
hir:: ItemKind :: ForeignMod { items, .. } => {
303
294
for item in items {
304
295
let item = self . cx . tcx . hir ( ) . foreign_item ( item. id ) ;
305
- self . visit_foreign_item_inner ( item, None ) ;
296
+ self . visit_foreign_item ( item, None , om ) ;
306
297
}
307
298
}
308
299
// If we're inlining, skip private items or item reexported as "_".
@@ -335,13 +326,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
335
326
res,
336
327
ident,
337
328
is_glob,
329
+ om,
338
330
please_inline,
339
331
) {
340
332
continue ;
341
333
}
342
334
}
343
335
344
- self . add_to_current_mod ( item, renamed, parent_id) ;
336
+ om . items . push ( ( item, renamed, parent_id) )
345
337
}
346
338
}
347
339
hir:: ItemKind :: Macro ( ref macro_def, _) => {
@@ -361,11 +353,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
361
353
let nonexported = !self . cx . tcx . has_attr ( def_id, sym:: macro_export) ;
362
354
363
355
if is_macro_2_0 || nonexported || self . inlining {
364
- self . add_to_current_mod ( item, renamed, None ) ;
356
+ om . items . push ( ( item, renamed, None ) ) ;
365
357
}
366
358
}
367
359
hir:: ItemKind :: Mod ( ref m) => {
368
- self . enter_mod ( item. hir_id ( ) , m, name) ;
360
+ om . mods . push ( self . visit_mod_contents ( item. hir_id ( ) , m, name, parent_id ) ) ;
369
361
}
370
362
hir:: ItemKind :: Fn ( ..)
371
363
| hir:: ItemKind :: ExternCrate ( ..)
@@ -376,92 +368,33 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
376
368
| hir:: ItemKind :: OpaqueTy ( ..)
377
369
| hir:: ItemKind :: Static ( ..)
378
370
| hir:: ItemKind :: Trait ( ..)
379
- | hir:: ItemKind :: TraitAlias ( ..) => {
380
- self . add_to_current_mod ( item, renamed, parent_id) ;
381
- }
371
+ | hir:: ItemKind :: TraitAlias ( ..) => om. items . push ( ( item, renamed, parent_id) ) ,
382
372
hir:: ItemKind :: Const ( ..) => {
383
373
// Underscore constants do not correspond to a nameable item and
384
374
// so are never useful in documentation.
385
375
if name != kw:: Underscore {
386
- self . add_to_current_mod ( item, renamed, parent_id) ;
376
+ om . items . push ( ( item, renamed, parent_id) ) ;
387
377
}
388
378
}
389
379
hir:: ItemKind :: Impl ( impl_) => {
390
380
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
391
381
// them up regardless of where they're located.
392
382
if !self . inlining && impl_. of_trait . is_none ( ) {
393
- self . add_to_current_mod ( item, None , None ) ;
383
+ om . items . push ( ( item, None , None ) ) ;
394
384
}
395
385
}
396
386
}
397
- true
398
387
}
399
388
400
- fn visit_foreign_item_inner (
389
+ fn visit_foreign_item (
401
390
& mut self ,
402
391
item : & ' tcx hir:: ForeignItem < ' _ > ,
403
392
renamed : Option < Symbol > ,
393
+ om : & mut Module < ' tcx > ,
404
394
) {
405
395
// If inlining we only want to include public functions.
406
396
if !self . inlining || self . cx . tcx . visibility ( item. owner_id ) . is_public ( ) {
407
- self . modules . last_mut ( ) . unwrap ( ) . foreigns . push ( ( item, renamed) ) ;
397
+ om . foreigns . push ( ( item, renamed) ) ;
408
398
}
409
399
}
410
-
411
- /// This method will create a new module and push it onto the "modules stack" then call
412
- /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
413
- /// add into the list of modules of the current module.
414
- fn enter_mod ( & mut self , id : hir:: HirId , m : & ' tcx hir:: Mod < ' tcx > , name : Symbol ) {
415
- self . modules . push ( Module :: new ( name, id, m. spans . inner_span ) ) ;
416
-
417
- self . visit_mod_contents ( id, m) ;
418
-
419
- let last = self . modules . pop ( ) . unwrap ( ) ;
420
- self . modules . last_mut ( ) . unwrap ( ) . mods . push ( last) ;
421
- }
422
- }
423
-
424
- // We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
425
- // such as impl blocks in const blocks.
426
- impl < ' a , ' tcx > Visitor < ' tcx > for RustdocVisitor < ' a , ' tcx > {
427
- type NestedFilter = nested_filter:: All ;
428
-
429
- fn nested_visit_map ( & mut self ) -> Self :: Map {
430
- self . cx . tcx . hir ( )
431
- }
432
-
433
- fn visit_item ( & mut self , i : & ' tcx hir:: Item < ' tcx > ) {
434
- let parent_id = if self . modules . len ( ) > 1 {
435
- Some ( self . modules [ self . modules . len ( ) - 2 ] . id )
436
- } else {
437
- None
438
- } ;
439
- if self . visit_item_inner ( i, None , parent_id) {
440
- walk_item ( self , i) ;
441
- }
442
- }
443
-
444
- fn visit_mod ( & mut self , _: & hir:: Mod < ' tcx > , _: Span , _: hir:: HirId ) {
445
- // Handled in `visit_item_inner`
446
- }
447
-
448
- fn visit_use ( & mut self , _: & hir:: UsePath < ' tcx > , _: hir:: HirId ) {
449
- // Handled in `visit_item_inner`
450
- }
451
-
452
- fn visit_path ( & mut self , _: & hir:: Path < ' tcx > , _: hir:: HirId ) {
453
- // Handled in `visit_item_inner`
454
- }
455
-
456
- fn visit_label ( & mut self , _: & rustc_ast:: Label ) {
457
- // Unneeded.
458
- }
459
-
460
- fn visit_infer ( & mut self , _: & hir:: InferArg ) {
461
- // Unneeded.
462
- }
463
-
464
- fn visit_lifetime ( & mut self , _: & hir:: Lifetime ) {
465
- // Unneeded.
466
- }
467
400
}
0 commit comments