Skip to content

Commit a954d63

Browse files
Improve code
1 parent a9d582f commit a954d63

File tree

1 file changed

+90
-93
lines changed

1 file changed

+90
-93
lines changed

src/librustdoc/visit_ast.rs

+90-93
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_hir::def_id::DefId;
88
use rustc_hir::intravisit::{walk_item, Visitor};
99
use rustc_hir::Node;
1010
use rustc_hir::CRATE_HIR_ID;
11-
use rustc_middle::hir::map::Map;
1211
use rustc_middle::hir::nested_filter;
1312
use rustc_middle::ty::TyCtxt;
1413
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
@@ -68,7 +67,6 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
6867
inside_public_path: bool,
6968
exact_paths: FxHashMap<DefId, Vec<Symbol>>,
7069
modules: Vec<Module<'tcx>>,
71-
map: Map<'tcx>,
7270
}
7371

7472
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -81,7 +79,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
8179
hir::CRATE_HIR_ID,
8280
cx.tcx.hir().root_module().spans.inner_span,
8381
);
84-
let map = cx.tcx.hir();
8582

8683
RustdocVisitor {
8784
cx,
@@ -90,7 +87,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9087
inside_public_path: true,
9188
exact_paths: FxHashMap::default(),
9289
modules: vec![om],
93-
map,
9490
}
9591
}
9692

@@ -99,6 +95,95 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9995
self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did));
10096
}
10197

98+
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();
103+
104+
// `#[macro_export] macro_rules!` items are reexported at the top level of the
105+
// crate, regardless of where they're defined. We want to document the
106+
// top level rexport of the macro, not its original definition, since
107+
// the rexport defines the path that a user will actually see. Accordingly,
108+
// we add the rexport as an item here, and then skip over the original
109+
// definition in `visit_item()` below.
110+
//
111+
// We also skip `#[macro_export] macro_rules!` that have already been inserted,
112+
// it can happen if within the same module a `#[macro_export] macro_rules!`
113+
// is declared but also a reexport of itself producing two exports of the same
114+
// macro in the same module.
115+
let mut inserted = FxHashSet::default();
116+
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));
124+
}
125+
}
126+
127+
self.cx.cache.hidden_cfg = self
128+
.cx
129+
.tcx
130+
.hir()
131+
.attrs(CRATE_HIR_ID)
132+
.iter()
133+
.filter(|attr| attr.has_name(sym::doc))
134+
.flat_map(|attr| attr.meta_item_list().into_iter().flatten())
135+
.filter(|attr| attr.has_name(sym::cfg_hide))
136+
.flat_map(|attr| {
137+
attr.meta_item_list()
138+
.unwrap_or(&[])
139+
.iter()
140+
.filter_map(|attr| {
141+
Cfg::parse(attr.meta_item()?)
142+
.map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
143+
.ok()
144+
})
145+
.collect::<Vec<_>>()
146+
})
147+
.chain(
148+
[Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)]
149+
.into_iter(),
150+
)
151+
.collect();
152+
153+
self.cx.cache.exact_paths = self.exact_paths;
154+
top_level_module
155+
}
156+
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);
162+
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
163+
// Keep track of if there were any private modules in the path.
164+
let orig_inside_public_path = self.inside_public_path;
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+
for &i in m.item_ids {
170+
let item = self.cx.tcx.hir().item(i);
171+
if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
172+
self.visit_item(item);
173+
}
174+
}
175+
for &i in m.item_ids {
176+
let item = self.cx.tcx.hir().item(i);
177+
// To match the way import precedence works, visit glob imports last.
178+
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
179+
// imported items appear last, then they'll be the ones that get discarded.
180+
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
181+
self.visit_item(item);
182+
}
183+
}
184+
self.inside_public_path = orig_inside_public_path;
185+
}
186+
102187
/// Tries to resolve the target of a `pub use` statement and inlines the
103188
/// target if it is defined locally and would not be documented otherwise,
104189
/// or when it is specifically requested with `please_inline`.
@@ -323,65 +408,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
323408
}
324409
}
325410

326-
pub(crate) fn visit(mut self) -> Module<'tcx> {
327-
let root_module = self.cx.tcx.hir().root_module();
328-
self.visit_mod_contents(CRATE_HIR_ID, root_module);
329-
330-
let mut top_level_module = self.modules.pop().unwrap();
331-
332-
// `#[macro_export] macro_rules!` items are reexported at the top level of the
333-
// crate, regardless of where they're defined. We want to document the
334-
// top level rexport of the macro, not its original definition, since
335-
// the rexport defines the path that a user will actually see. Accordingly,
336-
// we add the rexport as an item here, and then skip over the original
337-
// definition in `visit_item()` below.
338-
//
339-
// We also skip `#[macro_export] macro_rules!` that have already been inserted,
340-
// it can happen if within the same module a `#[macro_export] macro_rules!`
341-
// is declared but also a reexport of itself producing two exports of the same
342-
// macro in the same module.
343-
let mut inserted = FxHashSet::default();
344-
for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
345-
if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
346-
let Some(local_def_id) = def_id.as_local() &&
347-
self.cx.tcx.has_attr(def_id, sym::macro_export) &&
348-
inserted.insert(def_id)
349-
{
350-
let item = self.cx.tcx.hir().expect_item(local_def_id);
351-
top_level_module.items.push((item, None, None));
352-
}
353-
}
354-
355-
self.cx.cache.hidden_cfg = self
356-
.cx
357-
.tcx
358-
.hir()
359-
.attrs(CRATE_HIR_ID)
360-
.iter()
361-
.filter(|attr| attr.has_name(sym::doc))
362-
.flat_map(|attr| attr.meta_item_list().into_iter().flatten())
363-
.filter(|attr| attr.has_name(sym::cfg_hide))
364-
.flat_map(|attr| {
365-
attr.meta_item_list()
366-
.unwrap_or(&[])
367-
.iter()
368-
.filter_map(|attr| {
369-
Cfg::parse(attr.meta_item()?)
370-
.map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
371-
.ok()
372-
})
373-
.collect::<Vec<_>>()
374-
})
375-
.chain(
376-
[Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)]
377-
.into_iter(),
378-
)
379-
.collect();
380-
381-
self.cx.cache.exact_paths = self.exact_paths;
382-
top_level_module
383-
}
384-
385411
/// This method will create a new module and push it onto the "modules stack" then call
386412
/// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
387413
/// add into into the list of modules of the current module.
@@ -393,35 +419,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
393419
let last = self.modules.pop().unwrap();
394420
self.modules.last_mut().unwrap().mods.push(last);
395421
}
396-
397-
/// This method will go through the given module items in two passes:
398-
/// 1. The items which are not glob imports/reexports.
399-
/// 2. The glob imports/reexports.
400-
fn visit_mod_contents(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>) {
401-
debug!("Going through module {:?}", m);
402-
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
403-
// Keep track of if there were any private modules in the path.
404-
let orig_inside_public_path = self.inside_public_path;
405-
self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
406-
407-
// Reimplementation of `walk_mod`:
408-
for &i in m.item_ids {
409-
let item = self.cx.tcx.hir().item(i);
410-
if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
411-
self.visit_item(item);
412-
}
413-
}
414-
for &i in m.item_ids {
415-
let item = self.cx.tcx.hir().item(i);
416-
// To match the way import precedence works, visit glob imports last.
417-
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
418-
// imported items appear last, then they'll be the ones that get discarded.
419-
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
420-
self.visit_item(item);
421-
}
422-
}
423-
self.inside_public_path = orig_inside_public_path;
424-
}
425422
}
426423

427424
// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
@@ -430,7 +427,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
430427
type NestedFilter = nested_filter::All;
431428

432429
fn nested_visit_map(&mut self) -> Self::Map {
433-
self.map
430+
self.cx.tcx.hir()
434431
}
435432

436433
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {

0 commit comments

Comments
 (0)