diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 810bea4c5b09..a25cb0bacc5c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -14,7 +14,7 @@ use rustc_driver::{driver, target_features, abort_on_err}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; use rustc::hir::def_id::DefId; -use rustc::hir::def::Def; +use rustc::hir::def::{Def, ExportMap}; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt}; use rustc::hir::map as hir_map; @@ -74,6 +74,7 @@ pub struct DocContext<'a, 'tcx: 'a> { pub ty_substs: RefCell>, /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, + pub export_map: ExportMap, } impl<'b, 'tcx> DocContext<'b, 'tcx> { @@ -196,7 +197,7 @@ pub fn run_core(search_paths: SearchPaths, sess.fatal("Compilation failed, aborting rustdoc"); } - let ty::CrateAnalysis { access_levels, .. } = analysis; + let ty::CrateAnalysis { access_levels, export_map, .. } = analysis; // Convert from a NodeId set to a DefId set since we don't always have easy access // to the map from defid -> nodeid @@ -218,6 +219,7 @@ pub fn run_core(search_paths: SearchPaths, renderinfo: Default::default(), ty_substs: Default::default(), lt_substs: Default::default(), + export_map: export_map, }; debug!("crate: {:?}", ctxt.map.krate()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 1bbd67fb9be3..12d33dcb207f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -87,7 +87,7 @@ pub fn run(input: &str, config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); - let driver::ExpansionResult { defs, mut hir_forest, .. } = { + let driver::ExpansionResult { defs, mut hir_forest, analysis, .. } = { phase_2_configure_and_expand( &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(()) ).expect("phase_2_configure_and_expand aborted in rustdoc!") @@ -110,6 +110,7 @@ pub fn run(input: &str, renderinfo: Default::default(), ty_substs: Default::default(), lt_substs: Default::default(), + export_map: analysis.export_map, }; let mut v = RustdocVisitor::new(&ctx); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 6e47c037ad3d..b91d71198e81 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -85,8 +85,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &krate.module, None); // attach the crate's exported macros to the top-level module: - self.module.macros = krate.exported_macros.iter() - .map(|def| self.visit_macro(def)).collect(); + let macro_exports: Vec<_> = + krate.exported_macros.iter().map(|def| self.visit_macro(def)).collect(); + self.module.macros.extend(macro_exports); self.module.is_crate = true; } @@ -191,6 +192,28 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let item = self.cx.map.expect_item(i.id); self.visit_item(item, None, &mut om); } + if let Some(exports) = self.cx.export_map.get(&id) { + for export in exports { + if let Def::Macro(def_id) = export.def { + if def_id.krate == LOCAL_CRATE { + continue // These are `krate.exported_macros`, handled in `self.visit()`. + } + let def = self.cx.sess().cstore.load_macro(def_id, self.cx.sess()); + // FIXME(jseyfried) merge with `self.visit_macro()` + let matchers = def.body.chunks(4).map(|arm| arm[0].get_span()).collect(); + om.macros.push(Macro { + id: def.id, + attrs: def.attrs.clone().into(), + name: def.ident.name, + whence: def.span, + matchers: matchers, + stab: self.stability(def.id), + depr: self.deprecation(def.id), + imported_from: def.imported_from.map(|ident| ident.name), + }) + } + } + } om }