Skip to content

Commit 4af9132

Browse files
committed
Auto merge of #51611 - QuietMisdreavus:slippery-macros, r=ollie27
rustdoc: import cross-crate macros alongside everything else The thrilling conclusion of the cross-crate macro saga in rustdoc! After #51425 made sure we saw all the namespaces of an import (and prevented us from losing the `vec!` macro in std's documentation), here is the PR to handle cross-crate macro re-exports at the same time as everything else. This way, attributes like `#[doc(hidden)]` and `#[doc(no_inline)]` can be used to control how the documentation for these macros is seen, rather than rustdoc inlining every macro every time. Fixes #50647
2 parents 0ad8f9e + 61dc03c commit 4af9132

File tree

6 files changed

+124
-47
lines changed

6 files changed

+124
-47
lines changed

src/librustdoc/clean/inline.rs

+38-5
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, name))
108+
}
103109
_ => return None,
104110
};
105111
cx.renderinfo.borrow_mut().inlined.insert(did);
@@ -460,6 +466,33 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
460466
}
461467
}
462468

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+
463496
/// A trait's generics clause actually contains all of the predicates for all of
464497
/// its associated types as well. We specifically move these clauses to the
465498
/// associated types instead when displaying, so when we're generating the

src/librustdoc/visit_ast.rs

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

src/test/rustdoc/cross-crate-links.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ pub use all_item_types::FOO_STATIC;
6666
#[doc(no_inline)]
6767
pub use all_item_types::FOO_CONSTANT;
6868

69-
// @has 'foo/index.html' '//a[@href="../foo/macro.foo_macro.html"]' 'foo_macro'
69+
// @has 'foo/index.html' '//a[@href="../all_item_types/macro.foo_macro.html"]' 'foo_macro'
7070
#[doc(no_inline)]
7171
pub use all_item_types::foo_macro;
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+
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.renamed_macro.html
24+
// @!has - '//pre' 'some_macro'
25+
// @has macro_vis/index.html '//a/@href' 'macro.renamed_macro.html'
26+
#[doc(inline)]
27+
pub use qwop::some_macro as renamed_macro;
28+
29+
// @!has macro_vis/macro.other_macro.html
30+
// @!has macro_vis/index.html '//a/@href' 'macro.other_macro.html'
31+
// @!has - '//code' 'pub use qwop::other_macro;'
32+
#[doc(hidden)]
33+
pub use qwop::other_macro;
34+
35+
// @has macro_vis/index.html '//code' 'pub use qwop::super_macro;'
36+
// @!has macro_vis/macro.super_macro.html
37+
#[doc(no_inline)]
38+
pub use qwop::super_macro;
39+
40+
// @has macro_vis/macro.this_is_dope.html
41+
// @has macro_vis/index.html '//a/@href' 'macro.this_is_dope.html'
42+
/// What it says on the tin.
43+
#[macro_export]
44+
macro_rules! this_is_dope {
45+
() => {
46+
println!("yo check this out");
47+
};
48+
}

src/test/rustdoc/pub-use-extern-macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use macros::bar;
2323
#[doc(inline)]
2424
pub use macros::baz;
2525

26-
// @has pub_use_extern_macros/macro.quux.html
26+
// @!has pub_use_extern_macros/macro.quux.html
2727
// @!has pub_use_extern_macros/index.html '//code' 'pub use macros::quux;'
2828
#[doc(hidden)]
2929
pub use macros::quux;

0 commit comments

Comments
 (0)