|
13 | 13 | use std::iter::once;
|
14 | 14 |
|
15 | 15 | use syntax::ast;
|
16 |
| -use rustc::hir; |
| 16 | +use syntax::ext::base::MacroKind; |
| 17 | +use syntax_pos::Span; |
17 | 18 |
|
| 19 | +use rustc::hir; |
18 | 20 | use rustc::hir::def::{Def, CtorKind};
|
19 | 21 | use rustc::hir::def_id::DefId;
|
| 22 | +use rustc::middle::cstore::LoadedMacro; |
20 | 23 | use rustc::ty;
|
21 | 24 | use rustc::util::nodemap::FxHashSet;
|
22 | 25 |
|
23 | 26 | use core::{DocContext, DocAccessLevels};
|
24 | 27 | use doctree;
|
25 |
| -use clean::{self, GetDefId, get_auto_traits_with_def_id}; |
| 28 | +use clean::{self, GetDefId, ToSource, get_auto_traits_with_def_id}; |
26 | 29 |
|
27 | 30 | use super::Clean;
|
28 | 31 |
|
@@ -97,9 +100,12 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
|
97 | 100 | record_extern_fqn(cx, did, clean::TypeKind::Const);
|
98 | 101 | clean::ConstantItem(build_const(cx, did))
|
99 | 102 | }
|
100 |
| - // Macros are eagerly inlined back in visit_ast, don't show their export statements |
101 |
| - // FIXME(50647): the eager inline does not take doc(hidden)/doc(no_inline) into account |
102 |
| - Def::Macro(..) => return Some(Vec::new()), |
| 103 | + // FIXME(misdreavus): if attributes/derives come down here we should probably document them |
| 104 | + // separately |
| 105 | + Def::Macro(did, MacroKind::Bang) => { |
| 106 | + record_extern_fqn(cx, did, clean::TypeKind::Macro); |
| 107 | + clean::MacroItem(build_macro(cx, did, name)) |
| 108 | + } |
103 | 109 | _ => return None,
|
104 | 110 | };
|
105 | 111 | cx.renderinfo.borrow_mut().inlined.insert(did);
|
@@ -460,6 +466,33 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
|
460 | 466 | }
|
461 | 467 | }
|
462 | 468 |
|
| 469 | +fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> clean::Macro { |
| 470 | + let imported_from = cx.tcx.original_crate_name(did.krate); |
| 471 | + let def = match cx.cstore.load_macro_untracked(did, cx.sess()) { |
| 472 | + LoadedMacro::MacroDef(macro_def) => macro_def, |
| 473 | + // FIXME(jseyfried): document proc macro re-exports |
| 474 | + LoadedMacro::ProcMacro(..) => panic!("attempting to document proc-macro re-export"), |
| 475 | + }; |
| 476 | + |
| 477 | + let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node { |
| 478 | + let tts: Vec<_> = def.stream().into_trees().collect(); |
| 479 | + tts.chunks(4).map(|arm| arm[0].span()).collect() |
| 480 | + } else { |
| 481 | + unreachable!() |
| 482 | + }; |
| 483 | + |
| 484 | + let source = format!("macro_rules! {} {{\n{}}}", |
| 485 | + name.clean(cx), |
| 486 | + matchers.iter().map(|span| { |
| 487 | + format!(" {} => {{ ... }};\n", span.to_src(cx)) |
| 488 | + }).collect::<String>()); |
| 489 | + |
| 490 | + clean::Macro { |
| 491 | + source, |
| 492 | + imported_from: Some(imported_from).clean(cx), |
| 493 | + } |
| 494 | +} |
| 495 | + |
463 | 496 | /// A trait's generics clause actually contains all of the predicates for all of
|
464 | 497 | /// its associated types as well. We specifically move these clauses to the
|
465 | 498 | /// associated types instead when displaying, so when we're generating the
|
|
0 commit comments