Auto merge of #37773 - ollie27:rustdoc_inline_glob, r=brson
rustdoc: Fix some local inlining issues * Only inline public items when inlining glob imports. * Never inline while in a private module or a child of a private module. * Never inline impls. This allowed the removal of a workaround in the rendering code.
This commit is contained in:
commit
d88d06448e
6 changed files with 244 additions and 69 deletions
|
@ -257,8 +257,6 @@ pub struct Cache {
|
||||||
parent_stack: Vec<DefId>,
|
parent_stack: Vec<DefId>,
|
||||||
parent_is_trait_impl: bool,
|
parent_is_trait_impl: bool,
|
||||||
search_index: Vec<IndexItem>,
|
search_index: Vec<IndexItem>,
|
||||||
seen_modules: FxHashSet<DefId>,
|
|
||||||
seen_mod: bool,
|
|
||||||
stripped_mod: bool,
|
stripped_mod: bool,
|
||||||
deref_trait_did: Option<DefId>,
|
deref_trait_did: Option<DefId>,
|
||||||
deref_mut_trait_did: Option<DefId>,
|
deref_mut_trait_did: Option<DefId>,
|
||||||
|
@ -520,8 +518,6 @@ pub fn run(mut krate: clean::Crate,
|
||||||
parent_is_trait_impl: false,
|
parent_is_trait_impl: false,
|
||||||
extern_locations: FxHashMap(),
|
extern_locations: FxHashMap(),
|
||||||
primitive_locations: FxHashMap(),
|
primitive_locations: FxHashMap(),
|
||||||
seen_modules: FxHashSet(),
|
|
||||||
seen_mod: false,
|
|
||||||
stripped_mod: false,
|
stripped_mod: false,
|
||||||
access_levels: krate.access_levels.clone(),
|
access_levels: krate.access_levels.clone(),
|
||||||
orphan_impl_items: Vec::new(),
|
orphan_impl_items: Vec::new(),
|
||||||
|
@ -977,26 +973,16 @@ impl DocFolder for Cache {
|
||||||
_ => self.stripped_mod,
|
_ => self.stripped_mod,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inlining can cause us to visit the same item multiple times.
|
|
||||||
// (i.e. relevant for gathering impls and implementors)
|
|
||||||
let orig_seen_mod = if item.is_mod() {
|
|
||||||
let seen_this = self.seen_mod || !self.seen_modules.insert(item.def_id);
|
|
||||||
mem::replace(&mut self.seen_mod, seen_this)
|
|
||||||
} else {
|
|
||||||
self.seen_mod
|
|
||||||
};
|
|
||||||
|
|
||||||
// Register any generics to their corresponding string. This is used
|
// Register any generics to their corresponding string. This is used
|
||||||
// when pretty-printing types
|
// when pretty-printing types
|
||||||
if let Some(generics) = item.inner.generics() {
|
if let Some(generics) = item.inner.generics() {
|
||||||
self.generics(generics);
|
self.generics(generics);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.seen_mod {
|
|
||||||
// Propagate a trait methods' documentation to all implementors of the
|
// Propagate a trait methods' documentation to all implementors of the
|
||||||
// trait
|
// trait
|
||||||
if let clean::TraitItem(ref t) = item.inner {
|
if let clean::TraitItem(ref t) = item.inner {
|
||||||
self.traits.insert(item.def_id, t.clone());
|
self.traits.entry(item.def_id).or_insert_with(|| t.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all the implementors of traits.
|
// Collect all the implementors of traits.
|
||||||
|
@ -1009,7 +995,6 @@ impl DocFolder for Cache {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Index this method for searching later on
|
// Index this method for searching later on
|
||||||
if let Some(ref s) = item.name {
|
if let Some(ref s) = item.name {
|
||||||
|
@ -1186,13 +1171,11 @@ impl DocFolder for Cache {
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
if !self.seen_mod {
|
|
||||||
if let Some(did) = did {
|
if let Some(did) = did {
|
||||||
self.impls.entry(did).or_insert(vec![]).push(Impl {
|
self.impls.entry(did).or_insert(vec![]).push(Impl {
|
||||||
impl_item: item,
|
impl_item: item,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(item)
|
Some(item)
|
||||||
|
@ -1201,7 +1184,6 @@ impl DocFolder for Cache {
|
||||||
|
|
||||||
if pushed { self.stack.pop().unwrap(); }
|
if pushed { self.stack.pop().unwrap(); }
|
||||||
if parent_pushed { self.parent_stack.pop().unwrap(); }
|
if parent_pushed { self.parent_stack.pop().unwrap(); }
|
||||||
self.seen_mod = orig_seen_mod;
|
|
||||||
self.stripped_mod = orig_stripped_mod;
|
self.stripped_mod = orig_stripped_mod;
|
||||||
self.parent_is_trait_impl = orig_parent_is_trait_impl;
|
self.parent_is_trait_impl = orig_parent_is_trait_impl;
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -44,7 +44,9 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> {
|
||||||
pub attrs: hir::HirVec<ast::Attribute>,
|
pub attrs: hir::HirVec<ast::Attribute>,
|
||||||
pub cx: &'a core::DocContext<'a, 'tcx>,
|
pub cx: &'a core::DocContext<'a, 'tcx>,
|
||||||
view_item_stack: FxHashSet<ast::NodeId>,
|
view_item_stack: FxHashSet<ast::NodeId>,
|
||||||
inlining_from_glob: bool,
|
inlining: bool,
|
||||||
|
/// Is the current module and all of its parents public?
|
||||||
|
inside_public_path: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
|
@ -57,7 +59,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
attrs: hir::HirVec::new(),
|
attrs: hir::HirVec::new(),
|
||||||
cx: cx,
|
cx: cx,
|
||||||
view_item_stack: stack,
|
view_item_stack: stack,
|
||||||
inlining_from_glob: false,
|
inlining: false,
|
||||||
|
inside_public_path: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,10 +192,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
om.stab = self.stability(id);
|
om.stab = self.stability(id);
|
||||||
om.depr = self.deprecation(id);
|
om.depr = self.deprecation(id);
|
||||||
om.id = id;
|
om.id = id;
|
||||||
|
// Keep track of if there were any private modules in the path.
|
||||||
|
let orig_inside_public_path = self.inside_public_path;
|
||||||
|
self.inside_public_path &= vis == hir::Public;
|
||||||
for i in &m.item_ids {
|
for i in &m.item_ids {
|
||||||
let item = self.cx.map.expect_item(i.id);
|
let item = self.cx.map.expect_item(i.id);
|
||||||
self.visit_item(item, None, &mut om);
|
self.visit_item(item, None, &mut om);
|
||||||
}
|
}
|
||||||
|
self.inside_public_path = orig_inside_public_path;
|
||||||
if let Some(exports) = self.cx.export_map.get(&id) {
|
if let Some(exports) = self.cx.export_map.get(&id) {
|
||||||
for export in exports {
|
for export in exports {
|
||||||
if let Def::Macro(def_id) = export.def {
|
if let Def::Macro(def_id) = export.def {
|
||||||
|
@ -336,8 +343,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
let ret = match tcx.map.get(def_node_id) {
|
let ret = match tcx.map.get(def_node_id) {
|
||||||
hir_map::NodeItem(it) => {
|
hir_map::NodeItem(it) => {
|
||||||
|
let prev = mem::replace(&mut self.inlining, true);
|
||||||
if glob {
|
if glob {
|
||||||
let prev = mem::replace(&mut self.inlining_from_glob, true);
|
|
||||||
match it.node {
|
match it.node {
|
||||||
hir::ItemMod(ref m) => {
|
hir::ItemMod(ref m) => {
|
||||||
for i in &m.item_ids {
|
for i in &m.item_ids {
|
||||||
|
@ -348,10 +355,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
hir::ItemEnum(..) => {}
|
hir::ItemEnum(..) => {}
|
||||||
_ => { panic!("glob not mapped to a module or enum"); }
|
_ => { panic!("glob not mapped to a module or enum"); }
|
||||||
}
|
}
|
||||||
self.inlining_from_glob = prev;
|
|
||||||
} else {
|
} else {
|
||||||
self.visit_item(it, renamed, om);
|
self.visit_item(it, renamed, om);
|
||||||
}
|
}
|
||||||
|
self.inlining = prev;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -365,6 +372,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
debug!("Visiting item {:?}", item);
|
debug!("Visiting item {:?}", item);
|
||||||
let name = renamed.unwrap_or(item.name);
|
let name = renamed.unwrap_or(item.name);
|
||||||
match item.node {
|
match item.node {
|
||||||
|
hir::ItemForeignMod(ref fm) => {
|
||||||
|
// If inlining we only want to include public functions.
|
||||||
|
om.foreigns.push(if self.inlining {
|
||||||
|
hir::ForeignMod {
|
||||||
|
abi: fm.abi,
|
||||||
|
items: fm.items.iter().filter(|i| i.vis == hir::Public).cloned().collect(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fm.clone()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// If we're inlining, skip private items.
|
||||||
|
_ if self.inlining && item.vis != hir::Public => {}
|
||||||
hir::ItemExternCrate(ref p) => {
|
hir::ItemExternCrate(ref p) => {
|
||||||
let cstore = &self.cx.sess().cstore;
|
let cstore = &self.cx.sess().cstore;
|
||||||
om.extern_crates.push(ExternCrate {
|
om.extern_crates.push(ExternCrate {
|
||||||
|
@ -379,7 +399,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
hir::ItemUse(ref vpath) => {
|
hir::ItemUse(ref vpath) => {
|
||||||
let node = vpath.node.clone();
|
let node = vpath.node.clone();
|
||||||
let node = if item.vis == hir::Public {
|
// If there was a private module in the current path then don't bother inlining
|
||||||
|
// anything as it will probably be stripped anyway.
|
||||||
|
let node = if item.vis == hir::Public && self.inside_public_path {
|
||||||
let please_inline = item.attrs.iter().any(|item| {
|
let please_inline = item.attrs.iter().any(|item| {
|
||||||
match item.meta_item_list() {
|
match item.meta_item_list() {
|
||||||
Some(list) if item.check_name("doc") => {
|
Some(list) if item.check_name("doc") => {
|
||||||
|
@ -479,7 +501,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
om.traits.push(t);
|
om.traits.push(t);
|
||||||
},
|
},
|
||||||
|
|
||||||
hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
|
hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
|
||||||
|
// Don't duplicate impls when inlining, we'll pick them up
|
||||||
|
// regardless of where they're located.
|
||||||
|
if !self.inlining {
|
||||||
let i = Impl {
|
let i = Impl {
|
||||||
unsafety: unsafety,
|
unsafety: unsafety,
|
||||||
polarity: polarity,
|
polarity: polarity,
|
||||||
|
@ -494,13 +520,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
stab: self.stability(item.id),
|
stab: self.stability(item.id),
|
||||||
depr: self.deprecation(item.id),
|
depr: self.deprecation(item.id),
|
||||||
};
|
};
|
||||||
// Don't duplicate impls when inlining glob imports, we'll pick
|
|
||||||
// them up regardless of where they're located.
|
|
||||||
if !self.inlining_from_glob {
|
|
||||||
om.impls.push(i);
|
om.impls.push(i);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
|
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
|
||||||
|
// See comment above about ItemImpl.
|
||||||
|
if !self.inlining {
|
||||||
let i = DefaultImpl {
|
let i = DefaultImpl {
|
||||||
unsafety: unsafety,
|
unsafety: unsafety,
|
||||||
trait_: trait_ref.clone(),
|
trait_: trait_ref.clone(),
|
||||||
|
@ -508,14 +533,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
attrs: item.attrs.clone(),
|
attrs: item.attrs.clone(),
|
||||||
whence: item.span,
|
whence: item.span,
|
||||||
};
|
};
|
||||||
// see comment above about ItemImpl
|
|
||||||
if !self.inlining_from_glob {
|
|
||||||
om.def_traits.push(i);
|
om.def_traits.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemForeignMod(ref fm) => {
|
|
||||||
om.foreigns.push(fm.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/test/rustdoc/inline_local/glob-extern-no-defaults.rs
Normal file
35
src/test/rustdoc/inline_local/glob-extern-no-defaults.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: --no-defaults
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
mod mod1 {
|
||||||
|
extern {
|
||||||
|
pub fn public_fn();
|
||||||
|
fn private_fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use mod1::*;
|
||||||
|
|
||||||
|
// @has foo/index.html
|
||||||
|
// @has - "mod1"
|
||||||
|
// @has - "public_fn"
|
||||||
|
// @!has - "private_fn"
|
||||||
|
// @has foo/fn.public_fn.html
|
||||||
|
// @!has foo/fn.private_fn.html
|
||||||
|
|
||||||
|
// @has foo/mod1/index.html
|
||||||
|
// @has - "public_fn"
|
||||||
|
// @has - "private_fn"
|
||||||
|
// @has foo/mod1/fn.public_fn.html
|
||||||
|
// @has foo/mod1/fn.private_fn.html
|
31
src/test/rustdoc/inline_local/glob-extern.rs
Normal file
31
src/test/rustdoc/inline_local/glob-extern.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
mod mod1 {
|
||||||
|
extern {
|
||||||
|
pub fn public_fn();
|
||||||
|
fn private_fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use mod1::*;
|
||||||
|
|
||||||
|
// @has foo/index.html
|
||||||
|
// @!has - "mod1"
|
||||||
|
// @has - "public_fn"
|
||||||
|
// @!has - "private_fn"
|
||||||
|
// @has foo/fn.public_fn.html
|
||||||
|
// @!has foo/fn.private_fn.html
|
||||||
|
|
||||||
|
// @!has foo/mod1/index.html
|
||||||
|
// @has foo/mod1/fn.public_fn.html
|
||||||
|
// @!has foo/mod1/fn.private_fn.html
|
58
src/test/rustdoc/inline_local/glob-private-no-defaults.rs
Normal file
58
src/test/rustdoc/inline_local/glob-private-no-defaults.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: --no-defaults
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
mod mod1 {
|
||||||
|
mod mod2 {
|
||||||
|
pub struct Mod2Public;
|
||||||
|
struct Mod2Private;
|
||||||
|
}
|
||||||
|
pub use self::mod2::*;
|
||||||
|
|
||||||
|
pub struct Mod1Public;
|
||||||
|
struct Mod1Private;
|
||||||
|
}
|
||||||
|
pub use mod1::*;
|
||||||
|
|
||||||
|
// @has foo/index.html
|
||||||
|
// @has - "mod1"
|
||||||
|
// @has - "Mod1Public"
|
||||||
|
// @!has - "Mod1Private"
|
||||||
|
// @!has - "mod2"
|
||||||
|
// @has - "Mod2Public"
|
||||||
|
// @!has - "Mod2Private"
|
||||||
|
// @has foo/struct.Mod1Public.html
|
||||||
|
// @!has foo/struct.Mod1Private.html
|
||||||
|
// @has foo/struct.Mod2Public.html
|
||||||
|
// @!has foo/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @has foo/mod1/index.html
|
||||||
|
// @has - "mod2"
|
||||||
|
// @has - "Mod1Public"
|
||||||
|
// @has - "Mod1Private"
|
||||||
|
// @!has - "Mod2Public"
|
||||||
|
// @!has - "Mod2Private"
|
||||||
|
// @has foo/mod1/struct.Mod1Public.html
|
||||||
|
// @has foo/mod1/struct.Mod1Private.html
|
||||||
|
// @!has foo/mod1/struct.Mod2Public.html
|
||||||
|
// @!has foo/mod1/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @has foo/mod1/mod2/index.html
|
||||||
|
// @has - "Mod2Public"
|
||||||
|
// @has - "Mod2Private"
|
||||||
|
// @has foo/mod1/mod2/struct.Mod2Public.html
|
||||||
|
// @has foo/mod1/mod2/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @!has foo/mod2/index.html
|
||||||
|
// @!has foo/mod2/struct.Mod2Public.html
|
||||||
|
// @!has foo/mod2/struct.Mod2Private.html
|
49
src/test/rustdoc/inline_local/glob-private.rs
Normal file
49
src/test/rustdoc/inline_local/glob-private.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
mod mod1 {
|
||||||
|
mod mod2 {
|
||||||
|
pub struct Mod2Public;
|
||||||
|
struct Mod2Private;
|
||||||
|
}
|
||||||
|
pub use self::mod2::*;
|
||||||
|
|
||||||
|
pub struct Mod1Public;
|
||||||
|
struct Mod1Private;
|
||||||
|
}
|
||||||
|
pub use mod1::*;
|
||||||
|
|
||||||
|
// @has foo/index.html
|
||||||
|
// @!has - "mod1"
|
||||||
|
// @has - "Mod1Public"
|
||||||
|
// @!has - "Mod1Private"
|
||||||
|
// @!has - "mod2"
|
||||||
|
// @has - "Mod2Public"
|
||||||
|
// @!has - "Mod2Private"
|
||||||
|
// @has foo/struct.Mod1Public.html
|
||||||
|
// @!has foo/struct.Mod1Private.html
|
||||||
|
// @has foo/struct.Mod2Public.html
|
||||||
|
// @!has foo/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @!has foo/mod1/index.html
|
||||||
|
// @has foo/mod1/struct.Mod1Public.html
|
||||||
|
// @!has foo/mod1/struct.Mod1Private.html
|
||||||
|
// @!has foo/mod1/struct.Mod2Public.html
|
||||||
|
// @!has foo/mod1/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @!has foo/mod1/mod2/index.html
|
||||||
|
// @has foo/mod1/mod2/struct.Mod2Public.html
|
||||||
|
// @!has foo/mod1/mod2/struct.Mod2Private.html
|
||||||
|
|
||||||
|
// @!has foo/mod2/index.html
|
||||||
|
// @!has foo/mod2/struct.Mod2Public.html
|
||||||
|
// @!has foo/mod2/struct.Mod2Private.html
|
Loading…
Add table
Add a link
Reference in a new issue