Skip to content

Commit 3468548

Browse files
Improve code
1 parent 9b80a6d commit 3468548

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
@@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
88
use rustc_hir::intravisit::{walk_item, Visitor};
99
use rustc_hir::{Node, CRATE_HIR_ID};
10-
use rustc_middle::hir::map::Map;
1110
use rustc_middle::hir::nested_filter;
1211
use rustc_middle::ty::{DefIdTree, TyCtxt};
1312
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
@@ -74,7 +73,6 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
7473
inside_public_path: bool,
7574
exact_paths: DefIdMap<Vec<Symbol>>,
7675
modules: Vec<Module<'tcx>>,
77-
map: Map<'tcx>,
7876
}
7977

8078
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -87,7 +85,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
8785
CRATE_DEF_ID,
8886
cx.tcx.hir().root_module().spans.inner_span,
8987
);
90-
let map = cx.tcx.hir();
9188

9289
RustdocVisitor {
9390
cx,
@@ -96,7 +93,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9693
inside_public_path: true,
9794
exact_paths: Default::default(),
9895
modules: vec![om],
99-
map,
10096
}
10197
}
10298

@@ -105,6 +101,94 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
105101
self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did));
106102
}
107103

104+
pub(crate) fn visit(mut self) -> Module<'tcx> {
105+
let root_module = self.cx.tcx.hir().root_module();
106+
self.visit_mod_contents(CRATE_DEF_ID, root_module);
107+
108+
let mut top_level_module = self.modules.pop().unwrap();
109+
110+
// `#[macro_export] macro_rules!` items are reexported at the top level of the
111+
// crate, regardless of where they're defined. We want to document the
112+
// top level rexport of the macro, not its original definition, since
113+
// the rexport defines the path that a user will actually see. Accordingly,
114+
// we add the rexport as an item here, and then skip over the original
115+
// definition in `visit_item()` below.
116+
//
117+
// We also skip `#[macro_export] macro_rules!` that have already been inserted,
118+
// it can happen if within the same module a `#[macro_export] macro_rules!`
119+
// is declared but also a reexport of itself producing two exports of the same
120+
// macro in the same module.
121+
let mut inserted = FxHashSet::default();
122+
for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
123+
if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
124+
let Some(local_def_id) = def_id.as_local() &&
125+
self.cx.tcx.has_attr(def_id, sym::macro_export) &&
126+
inserted.insert(def_id)
127+
{
128+
let item = self.cx.tcx.hir().expect_item(local_def_id);
129+
top_level_module.items.push((item, None, None));
130+
}
131+
}
132+
133+
self.cx.cache.hidden_cfg = self
134+
.cx
135+
.tcx
136+
.hir()
137+
.attrs(CRATE_HIR_ID)
138+
.iter()
139+
.filter(|attr| attr.has_name(sym::doc))
140+
.flat_map(|attr| attr.meta_item_list().into_iter().flatten())
141+
.filter(|attr| attr.has_name(sym::cfg_hide))
142+
.flat_map(|attr| {
143+
attr.meta_item_list()
144+
.unwrap_or(&[])
145+
.iter()
146+
.filter_map(|attr| {
147+
Cfg::parse(attr.meta_item()?)
148+
.map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
149+
.ok()
150+
})
151+
.collect::<Vec<_>>()
152+
})
153+
.chain(
154+
[Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)]
155+
.into_iter(),
156+
)
157+
.collect();
158+
159+
self.cx.cache.exact_paths = self.exact_paths;
160+
top_level_module
161+
}
162+
163+
/// This method will go through the given module items in two passes:
164+
/// 1. The items which are not glob imports/reexports.
165+
/// 2. The glob imports/reexports.
166+
fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) {
167+
debug!("Going through module {:?}", m);
168+
// Keep track of if there were any private modules in the path.
169+
let orig_inside_public_path = self.inside_public_path;
170+
self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public();
171+
172+
// Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
173+
// the second loop):
174+
for &i in m.item_ids {
175+
let item = self.cx.tcx.hir().item(i);
176+
if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
177+
self.visit_item(item);
178+
}
179+
}
180+
for &i in m.item_ids {
181+
let item = self.cx.tcx.hir().item(i);
182+
// To match the way import precedence works, visit glob imports last.
183+
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
184+
// imported items appear last, then they'll be the ones that get discarded.
185+
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
186+
self.visit_item(item);
187+
}
188+
}
189+
self.inside_public_path = orig_inside_public_path;
190+
}
191+
108192
/// Tries to resolve the target of a `pub use` statement and inlines the
109193
/// target if it is defined locally and would not be documented otherwise,
110194
/// or when it is specifically requested with `please_inline`.
@@ -197,7 +281,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
197281
&mut self,
198282
item: &'tcx hir::Item<'_>,
199283
renamed: Option<Symbol>,
200-
parent_id: Option<hir::HirId>,
284+
parent_id: Option<LocalDefId>,
201285
) {
202286
self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
203287
}
@@ -330,65 +414,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
330414
}
331415
}
332416

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

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

438435
fn nested_visit_map(&mut self) -> Self::Map {
439-
self.map
436+
self.cx.tcx.hir()
440437
}
441438

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

0 commit comments

Comments
 (0)