Skip to content

Commit d4387b3

Browse files
rustdoc: import cross-crate macros alongside everything else
1 parent 499583a commit d4387b3

File tree

4 files changed

+116
-45
lines changed

4 files changed

+116
-45
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313
use std::iter::once;
1414

1515
use syntax::ast;
16-
use rustc::hir;
16+
use syntax::ext::base::MacroKind;
17+
use syntax_pos::Span;
1718

19+
use rustc::hir;
1820
use rustc::hir::def::{Def, CtorKind};
1921
use rustc::hir::def_id::DefId;
22+
use rustc::middle::cstore::LoadedMacro;
2023
use rustc::ty;
2124
use rustc::util::nodemap::FxHashSet;
2225

2326
use core::{DocContext, DocAccessLevels};
2427
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};
2629

2730
use super::Clean;
2831

@@ -97,9 +100,12 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
97100
record_extern_fqn(cx, did, clean::TypeKind::Const);
98101
clean::ConstantItem(build_const(cx, did))
99102
}
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))
108+
}
103109
_ => return None,
104110
};
105111
cx.renderinfo.borrow_mut().inlined.insert(did);
@@ -457,6 +463,33 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
457463
}
458464
}
459465

466+
fn build_macro(cx: &DocContext, did: DefId) -> clean::Macro {
467+
let imported_from = cx.tcx.original_crate_name(did.krate);
468+
let def = match cx.cstore.load_macro_untracked(did, cx.sess()) {
469+
LoadedMacro::MacroDef(macro_def) => macro_def,
470+
// FIXME(jseyfried): document proc macro re-exports
471+
LoadedMacro::ProcMacro(..) => panic!("attempting to document proc-macro re-export"),
472+
};
473+
474+
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
475+
let tts: Vec<_> = def.stream().into_trees().collect();
476+
tts.chunks(4).map(|arm| arm[0].span()).collect()
477+
} else {
478+
unreachable!()
479+
};
480+
481+
let source = format!("macro_rules! {} {{\n{}}}",
482+
def.ident.name.clean(cx),
483+
matchers.iter().map(|span| {
484+
format!(" {} => {{ ... }};\n", span.to_src(cx))
485+
}).collect::<String>());
486+
487+
clean::Macro {
488+
source,
489+
imported_from: Some(imported_from).clean(cx),
490+
}
491+
}
492+
460493
/// A trait's generics clause actually contains all of the predicates for all of
461494
/// its associated types as well. We specifically move these clauses to the
462495
/// associated types instead when displaying, so when we're generating the

src/librustdoc/visit_ast.rs

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ use syntax_pos::Span;
2121
use rustc::hir::map as hir_map;
2222
use rustc::hir::def::Def;
2323
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
24-
use rustc::middle::cstore::{LoadedMacro, CrateStore};
24+
use rustc::middle::cstore::CrateStore;
2525
use rustc::middle::privacy::AccessLevel;
26-
use rustc::ty::Visibility;
2726
use rustc::util::nodemap::{FxHashSet, FxHashMap};
2827

2928
use rustc::hir;
@@ -215,44 +214,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
215214
self.visit_item(item, None, &mut om);
216215
}
217216
self.inside_public_path = orig_inside_public_path;
218-
let def_id = self.cx.tcx.hir.local_def_id(id);
219-
if let Some(exports) = self.cx.tcx.module_exports(def_id) {
220-
for export in exports.iter().filter(|e| e.vis == Visibility::Public) {
221-
if let Def::Macro(def_id, ..) = export.def {
222-
// FIXME(50647): this eager macro inlining does not take
223-
// doc(hidden)/doc(no_inline) into account
224-
if def_id.krate == LOCAL_CRATE {
225-
continue // These are `krate.exported_macros`, handled in `self.visit()`.
226-
}
227-
228-
let imported_from = self.cx.tcx.original_crate_name(def_id.krate);
229-
let def = match self.cstore.load_macro_untracked(def_id, self.cx.sess()) {
230-
LoadedMacro::MacroDef(macro_def) => macro_def,
231-
// FIXME(jseyfried): document proc macro re-exports
232-
LoadedMacro::ProcMacro(..) => continue,
233-
};
234-
235-
let matchers = if let ast::ItemKind::MacroDef(ref def) = def.node {
236-
let tts: Vec<_> = def.stream().into_trees().collect();
237-
tts.chunks(4).map(|arm| arm[0].span()).collect()
238-
} else {
239-
unreachable!()
240-
};
241-
242-
debug!("inlining macro {}", def.ident.name);
243-
om.macros.push(Macro {
244-
def_id,
245-
attrs: def.attrs.clone().into(),
246-
name: def.ident.name,
247-
whence: self.cx.tcx.def_span(def_id),
248-
matchers,
249-
stab: self.cx.tcx.lookup_stability(def_id).cloned(),
250-
depr: self.cx.tcx.lookup_deprecation(def_id),
251-
imported_from: Some(imported_from),
252-
})
253-
}
254-
}
255-
}
256217
om
257218
}
258219

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "qwop"]
12+
13+
/// (writen on a spider's web) Some Macro
14+
#[macro_export]
15+
macro_rules! some_macro {
16+
() => {
17+
println!("this is some macro, for sure");
18+
};
19+
}
20+
21+
/// Some other macro, to fill space.
22+
#[macro_export]
23+
macro_rules! other_macro {
24+
() => {
25+
println!("this is some other macro, whatev");
26+
};
27+
}
28+
29+
/// This macro is so cool, it's Super.
30+
#[macro_export]
31+
macro_rules! super_macro {
32+
() => {
33+
println!("is it a bird? a plane? no, it's Super Macro!");
34+
};
35+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:macro-vis.rs
12+
// build-aux-docs
13+
// ignore-cross-compile
14+
15+
#![feature(use_extern_macros)]
16+
17+
#[macro_use] extern crate qwop;
18+
19+
// @has macro_vis/macro.some_macro.html
20+
// @has macro_vis/index.html '//a/@href' 'macro.some_macro.html'
21+
pub use qwop::some_macro;
22+
23+
// @!has macro_vis/macro.other_macro.html
24+
// @!has macro_vis/index.html '//a/@href' 'macro.other_macro.html'
25+
// @!has - '//code' 'pub use qwop::other_macro;'
26+
#[doc(hidden)]
27+
pub use qwop::other_macro;
28+
29+
// @has macro_vis/index.html '//code' 'pub use qwop::super_macro;'
30+
// @!has macro_vis/macro.super_macro.html
31+
#[doc(no_inline)]
32+
pub use qwop::super_macro;
33+
34+
// @has macro_vis/macro.this_is_dope.html
35+
// @has macro_vis/index.html '//a/@href' 'macro.this_is_dope.html'
36+
/// What it says on the tin.
37+
#[macro_export]
38+
macro_rules! this_is_dope {
39+
() => {
40+
println!("yo check this out");
41+
};
42+
}

0 commit comments

Comments
 (0)