@@ -5,10 +5,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
55use rustc_hir as hir;
66use rustc_hir:: def:: { DefKind , Res } ;
77use rustc_hir:: def_id:: DefId ;
8- use rustc_hir:: intravisit:: { walk_item, Visitor } ;
98use rustc_hir:: Node ;
109use rustc_hir:: CRATE_HIR_ID ;
11- use rustc_middle:: hir:: nested_filter;
1210use rustc_middle:: ty:: TyCtxt ;
1311use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
1412use rustc_span:: symbol:: { kw, sym, Symbol } ;
@@ -59,34 +57,29 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool
5957 false
6058}
6159
60+ // Also, is there some reason that this doesn't use the 'visit'
61+ // framework from syntax?.
62+
6263pub ( crate ) struct RustdocVisitor < ' a , ' tcx > {
6364 cx : & ' a mut core:: DocContext < ' tcx > ,
6465 view_item_stack : FxHashSet < hir:: HirId > ,
6566 inlining : bool ,
6667 /// Are the current module and all of its parents public?
6768 inside_public_path : bool ,
6869 exact_paths : FxHashMap < DefId , Vec < Symbol > > ,
69- modules : Vec < Module < ' tcx > > ,
7070}
7171
7272impl < ' a , ' tcx > RustdocVisitor < ' a , ' tcx > {
7373 pub ( crate ) fn new ( cx : & ' a mut core:: DocContext < ' tcx > ) -> RustdocVisitor < ' a , ' tcx > {
7474 // If the root is re-exported, terminate all recursion.
7575 let mut stack = FxHashSet :: default ( ) ;
7676 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-
8377 RustdocVisitor {
8478 cx,
8579 view_item_stack : stack,
8680 inlining : false ,
8781 inside_public_path : true ,
8882 exact_paths : FxHashMap :: default ( ) ,
89- modules : vec ! [ om] ,
9083 }
9184 }
9285
@@ -96,10 +89,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9689 }
9790
9891 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+ ) ;
10398
10499 // `#[macro_export] macro_rules!` items are reexported at the top level of the
105100 // crate, regardless of where they're defined. We want to document the
@@ -114,13 +109,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
114109 // macro in the same module.
115110 let mut inserted = FxHashSet :: default ( ) ;
116111 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+ }
124121 }
125122 }
126123
@@ -154,34 +151,36 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
154151 top_level_module
155152 }
156153
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 ) ;
162162 let def_id = self . cx . tcx . hir ( ) . local_def_id ( id) . to_def_id ( ) ;
163163 // Keep track of if there were any private modules in the path.
164164 let orig_inside_public_path = self . inside_public_path ;
165165 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):
169166 for & i in m. item_ids {
170167 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 ;
173170 }
171+ self . visit_item ( item, None , & mut om, parent_id) ;
174172 }
175173 for & i in m. item_ids {
176174 let item = self . cx . tcx . hir ( ) . item ( i) ;
177175 // To match the way import precedence works, visit glob imports last.
178176 // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
179177 // imported items appear last, then they'll be the ones that get discarded.
180178 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 ) ;
182180 }
183181 }
184182 self . inside_public_path = orig_inside_public_path;
183+ om
185184 }
186185
187186 /// Tries to resolve the target of a `pub use` statement and inlines the
@@ -199,6 +198,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
199198 res : Res ,
200199 renamed : Option < Symbol > ,
201200 glob : bool ,
201+ om : & mut Module < ' tcx > ,
202202 please_inline : bool ,
203203 ) -> bool {
204204 debug ! ( "maybe_inline_local res: {:?}" , res) ;
@@ -249,20 +249,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
249249 let prev = mem:: replace ( & mut self . inlining , true ) ;
250250 for & i in m. item_ids {
251251 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) ) ;
253253 }
254254 self . inlining = prev;
255255 true
256256 }
257257 Node :: Item ( it) if !glob => {
258258 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) ) ;
260260 self . inlining = prev;
261261 true
262262 }
263263 Node :: ForeignItem ( it) if !glob => {
264264 let prev = mem:: replace ( & mut self . inlining , true ) ;
265- self . visit_foreign_item_inner ( it, renamed) ;
265+ self . visit_foreign_item ( it, renamed, om ) ;
266266 self . inlining = prev;
267267 true
268268 }
@@ -272,22 +272,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
272272 ret
273273 }
274274
275- #[ inline]
276- fn add_to_current_mod (
275+ fn visit_item (
277276 & mut self ,
278277 item : & ' tcx hir:: Item < ' _ > ,
279278 renamed : Option < Symbol > ,
279+ om : & mut Module < ' tcx > ,
280280 parent_id : Option < hir:: HirId > ,
281281 ) {
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 {
291282 debug ! ( "visiting item {:?}" , item) ;
292283 let name = renamed. unwrap_or ( item. ident . name ) ;
293284
@@ -302,7 +293,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
302293 hir:: ItemKind :: ForeignMod { items, .. } => {
303294 for item in items {
304295 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 ) ;
306297 }
307298 }
308299 // If we're inlining, skip private items or item reexported as "_".
@@ -335,13 +326,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
335326 res,
336327 ident,
337328 is_glob,
329+ om,
338330 please_inline,
339331 ) {
340332 continue ;
341333 }
342334 }
343335
344- self . add_to_current_mod ( item, renamed, parent_id) ;
336+ om . items . push ( ( item, renamed, parent_id) )
345337 }
346338 }
347339 hir:: ItemKind :: Macro ( ref macro_def, _) => {
@@ -361,11 +353,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
361353 let nonexported = !self . cx . tcx . has_attr ( def_id, sym:: macro_export) ;
362354
363355 if is_macro_2_0 || nonexported || self . inlining {
364- self . add_to_current_mod ( item, renamed, None ) ;
356+ om . items . push ( ( item, renamed, None ) ) ;
365357 }
366358 }
367359 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 ) ) ;
369361 }
370362 hir:: ItemKind :: Fn ( ..)
371363 | hir:: ItemKind :: ExternCrate ( ..)
@@ -376,92 +368,33 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
376368 | hir:: ItemKind :: OpaqueTy ( ..)
377369 | hir:: ItemKind :: Static ( ..)
378370 | 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) ) ,
382372 hir:: ItemKind :: Const ( ..) => {
383373 // Underscore constants do not correspond to a nameable item and
384374 // so are never useful in documentation.
385375 if name != kw:: Underscore {
386- self . add_to_current_mod ( item, renamed, parent_id) ;
376+ om . items . push ( ( item, renamed, parent_id) ) ;
387377 }
388378 }
389379 hir:: ItemKind :: Impl ( impl_) => {
390380 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
391381 // them up regardless of where they're located.
392382 if !self . inlining && impl_. of_trait . is_none ( ) {
393- self . add_to_current_mod ( item, None , None ) ;
383+ om . items . push ( ( item, None , None ) ) ;
394384 }
395385 }
396386 }
397- true
398387 }
399388
400- fn visit_foreign_item_inner (
389+ fn visit_foreign_item (
401390 & mut self ,
402391 item : & ' tcx hir:: ForeignItem < ' _ > ,
403392 renamed : Option < Symbol > ,
393+ om : & mut Module < ' tcx > ,
404394 ) {
405395 // If inlining we only want to include public functions.
406396 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) ) ;
408398 }
409399 }
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- }
467400}
0 commit comments