Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b1543a1

Browse files
committedApr 2, 2016
Make the rendering process less pass-aware
Instead of hardcoding knowledge about the strip-private pass into the rendering process we represent (some) stripped items as `ItemEnum::StrippedItem`. Rustdoc will, for example, generate redirect pages for public items contained in private modules which have been re-exported to somewhere externally reachable - this will now not only work for the `strip-private` pass, but for other passes as well, such as the `strip-hidden` pass.
1 parent 4583dc9 commit b1543a1

File tree

8 files changed

+244
-146
lines changed

8 files changed

+244
-146
lines changed
 

‎src/librustdoc/clean/mod.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use std::env::current_dir;
5353
use core::DocContext;
5454
use doctree;
5555
use visit_ast;
56+
use html::item_type::ItemType;
5657

5758
/// A stable identifier to the particular version of JSON output.
5859
/// Increment this when the `Crate` and related structures change.
@@ -273,36 +274,40 @@ impl Item {
273274
}
274275
pub fn is_crate(&self) -> bool {
275276
match self.inner {
276-
ModuleItem(Module { items: _, is_crate: true }) => true,
277-
_ => false
277+
StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
278+
ModuleItem(Module { is_crate: true, ..}) => true,
279+
_ => false,
278280
}
279281
}
280282
pub fn is_mod(&self) -> bool {
281-
match self.inner { ModuleItem(..) => true, _ => false }
283+
ItemType::from_item(self) == ItemType::Module
282284
}
283285
pub fn is_trait(&self) -> bool {
284-
match self.inner { TraitItem(..) => true, _ => false }
286+
ItemType::from_item(self) == ItemType::Trait
285287
}
286288
pub fn is_struct(&self) -> bool {
287-
match self.inner { StructItem(..) => true, _ => false }
289+
ItemType::from_item(self) == ItemType::Struct
288290
}
289291
pub fn is_enum(&self) -> bool {
290-
match self.inner { EnumItem(..) => true, _ => false }
292+
ItemType::from_item(self) == ItemType::Module
291293
}
292294
pub fn is_fn(&self) -> bool {
293-
match self.inner { FunctionItem(..) => true, _ => false }
295+
ItemType::from_item(self) == ItemType::Function
294296
}
295297
pub fn is_associated_type(&self) -> bool {
296-
match self.inner { AssociatedTypeItem(..) => true, _ => false }
298+
ItemType::from_item(self) == ItemType::AssociatedType
297299
}
298300
pub fn is_associated_const(&self) -> bool {
299-
match self.inner { AssociatedConstItem(..) => true, _ => false }
301+
ItemType::from_item(self) == ItemType::AssociatedConst
300302
}
301303
pub fn is_method(&self) -> bool {
302-
match self.inner { MethodItem(..) => true, _ => false }
304+
ItemType::from_item(self) == ItemType::Method
303305
}
304306
pub fn is_ty_method(&self) -> bool {
305-
match self.inner { TyMethodItem(..) => true, _ => false }
307+
ItemType::from_item(self) == ItemType::TyMethod
308+
}
309+
pub fn is_stripped(&self) -> bool {
310+
match self.inner { StrippedItem(..) => true, _ => false }
306311
}
307312

308313
pub fn stability_class(&self) -> String {
@@ -352,6 +357,8 @@ pub enum ItemEnum {
352357
AssociatedConstItem(Type, Option<String>),
353358
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
354359
DefaultImplItem(DefaultImpl),
360+
/// An item that has been stripped by a rustdoc pass
361+
StrippedItem(Box<ItemEnum>),
355362
}
356363

357364
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

‎src/librustdoc/fold.rs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,50 @@
1010

1111
use clean::*;
1212

13+
pub enum FoldItem {
14+
Retain(Item),
15+
Strip(Item),
16+
Erase,
17+
}
18+
19+
impl FoldItem {
20+
pub fn fold(self) -> Option<Item> {
21+
match self {
22+
FoldItem::Erase => None,
23+
FoldItem::Retain(i) => Some(i),
24+
FoldItem::Strip(item@ Item { inner: StrippedItem(..), .. } ) => Some(item),
25+
FoldItem::Strip(mut i) => {
26+
i.inner = StrippedItem(box i.inner);
27+
Some(i)
28+
}
29+
}
30+
}
31+
}
32+
1333
pub trait DocFolder : Sized {
1434
fn fold_item(&mut self, item: Item) -> Option<Item> {
1535
self.fold_item_recur(item)
1636
}
1737

1838
/// don't override!
19-
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
20-
let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item;
21-
let inner = match inner {
39+
fn fold_inner_recur(&mut self, inner: ItemEnum) -> ItemEnum {
40+
match inner {
41+
StrippedItem(..) => unreachable!(),
42+
ModuleItem(i) => {
43+
ModuleItem(self.fold_mod(i))
44+
},
2245
StructItem(mut i) => {
2346
let num_fields = i.fields.len();
2447
i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
25-
i.fields_stripped |= num_fields != i.fields.len();
48+
i.fields_stripped |= num_fields != i.fields.len() ||
49+
i.fields.iter().any(|f| f.is_stripped());
2650
StructItem(i)
2751
},
28-
ModuleItem(i) => {
29-
ModuleItem(self.fold_mod(i))
30-
},
3152
EnumItem(mut i) => {
3253
let num_variants = i.variants.len();
3354
i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect();
34-
i.variants_stripped |= num_variants != i.variants.len();
55+
i.variants_stripped |= num_variants != i.variants.len() ||
56+
i.variants.iter().any(|f| f.is_stripped());
3557
EnumItem(i)
3658
},
3759
TraitItem(mut i) => {
@@ -48,13 +70,24 @@ pub trait DocFolder : Sized {
4870
StructVariant(mut j) => {
4971
let num_fields = j.fields.len();
5072
j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
51-
j.fields_stripped |= num_fields != j.fields.len();
73+
j.fields_stripped |= num_fields != j.fields.len() ||
74+
j.fields.iter().any(|f| f.is_stripped());
5275
VariantItem(Variant {kind: StructVariant(j), ..i2})
5376
},
5477
_ => VariantItem(i2)
5578
}
5679
},
5780
x => x
81+
}
82+
}
83+
84+
/// don't override!
85+
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
86+
let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item;
87+
88+
let inner = match inner {
89+
StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
90+
_ => self.fold_inner_recur(inner),
5891
};
5992

6093
Some(Item { attrs: attrs, name: name, source: source, inner: inner,
@@ -70,9 +103,8 @@ pub trait DocFolder : Sized {
70103
}
71104

72105
fn fold_crate(&mut self, mut c: Crate) -> Crate {
73-
c.module = c.module.and_then(|module| {
74-
self.fold_item(module)
75-
});
106+
c.module = c.module.and_then(|module| self.fold_item(module));
107+
76108
c.external_traits = c.external_traits.into_iter().map(|(k, mut v)| {
77109
v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
78110
(k, v)

‎src/librustdoc/html/item_type.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ pub enum ItemType {
4444

4545
impl ItemType {
4646
pub fn from_item(item: &clean::Item) -> ItemType {
47-
match item.inner {
47+
let inner = match item.inner {
48+
clean::StrippedItem(box ref item) => item,
49+
ref inner@_ => inner,
50+
};
51+
52+
match *inner {
4853
clean::ModuleItem(..) => ItemType::Module,
4954
clean::ExternCrateItem(..) => ItemType::ExternCrate,
5055
clean::ImportItem(..) => ItemType::Import,
@@ -67,6 +72,7 @@ impl ItemType {
6772
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
6873
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
6974
clean::DefaultImplItem(..) => ItemType::Impl,
75+
clean::StrippedItem(..) => unreachable!(),
7076
}
7177
}
7278

‎src/librustdoc/html/render.rs

Lines changed: 84 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,7 @@ pub struct Cache {
245245
parent_stack: Vec<DefId>,
246246
parent_is_trait_impl: bool,
247247
search_index: Vec<IndexItem>,
248-
privmod: bool,
249-
remove_priv: bool,
248+
stripped_mod: bool,
250249
access_levels: AccessLevels<DefId>,
251250
deref_trait_did: Option<DefId>,
252251

@@ -492,8 +491,7 @@ pub fn run(mut krate: clean::Crate,
492491
parent_is_trait_impl: false,
493492
extern_locations: HashMap::new(),
494493
primitive_locations: HashMap::new(),
495-
remove_priv: cx.passes.contains("strip-private"),
496-
privmod: false,
494+
stripped_mod: false,
497495
access_levels: access_levels,
498496
orphan_methods: Vec::new(),
499497
traits: mem::replace(&mut krate.external_traits, HashMap::new()),
@@ -874,7 +872,6 @@ impl<'a> DocFolder for SourceCollector<'a> {
874872
}
875873
};
876874
}
877-
878875
self.fold_item_recur(item)
879876
}
880877
}
@@ -938,14 +935,15 @@ impl<'a> SourceCollector<'a> {
938935

939936
impl DocFolder for Cache {
940937
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
941-
// If this is a private module, we don't want it in the search index.
942-
let orig_privmod = match item.inner {
943-
clean::ModuleItem(..) => {
944-
let prev = self.privmod;
945-
self.privmod = prev || (self.remove_priv && item.visibility != Some(hir::Public));
938+
// If this is a stripped module,
939+
// we don't want it or its children in the search index.
940+
let orig_stripped_mod = match item.inner {
941+
clean::StrippedItem(box clean::ModuleItem(..)) => {
942+
let prev = self.stripped_mod;
943+
self.stripped_mod = true;
946944
prev
947945
}
948-
_ => self.privmod,
946+
_ => self.stripped_mod,
949947
};
950948

951949
// Register any generics to their corresponding string. This is used
@@ -983,6 +981,7 @@ impl DocFolder for Cache {
983981
// Index this method for searching later on
984982
if let Some(ref s) = item.name {
985983
let (parent, is_method) = match item.inner {
984+
clean::StrippedItem(..) => ((None, None), false),
986985
clean::AssociatedConstItem(..) |
987986
clean::TypedefItem(_, true) if self.parent_is_trait_impl => {
988987
// skip associated items in trait impls
@@ -1027,14 +1026,15 @@ impl DocFolder for Cache {
10271026
};
10281027

10291028
match parent {
1030-
(parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => {
1029+
(parent, Some(path)) if is_method || (!self.stripped_mod && !hidden_field) => {
10311030
// Needed to determine `self` type.
10321031
let parent_basename = self.parent_stack.first().and_then(|parent| {
10331032
match self.paths.get(parent) {
10341033
Some(&(ref fqp, _)) => Some(fqp[fqp.len() - 1].clone()),
10351034
_ => None
10361035
}
10371036
});
1037+
debug_assert!(!item.is_stripped());
10381038

10391039
// A crate has a module at its root, containing all items,
10401040
// which should not be indexed. The crate-item itself is
@@ -1051,7 +1051,7 @@ impl DocFolder for Cache {
10511051
});
10521052
}
10531053
}
1054-
(Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> {
1054+
(Some(parent), None) if is_method || (!self.stripped_mod && !hidden_field)=> {
10551055
if parent.is_local() {
10561056
// We have a parent, but we don't know where they're
10571057
// defined yet. Wait for later to index this item.
@@ -1075,7 +1075,7 @@ impl DocFolder for Cache {
10751075
clean::StructItem(..) | clean::EnumItem(..) |
10761076
clean::TypedefItem(..) | clean::TraitItem(..) |
10771077
clean::FunctionItem(..) | clean::ModuleItem(..) |
1078-
clean::ForeignFunctionItem(..) if !self.privmod => {
1078+
clean::ForeignFunctionItem(..) if !self.stripped_mod => {
10791079
// Reexported items mean that the same id can show up twice
10801080
// in the rustdoc ast that we're looking at. We know,
10811081
// however, that a reexported item doesn't show up in the
@@ -1093,7 +1093,7 @@ impl DocFolder for Cache {
10931093
}
10941094
// link variants to their parent enum because pages aren't emitted
10951095
// for each variant
1096-
clean::VariantItem(..) if !self.privmod => {
1096+
clean::VariantItem(..) if !self.stripped_mod => {
10971097
let mut stack = self.stack.clone();
10981098
stack.pop();
10991099
self.paths.insert(item.def_id, (stack, ItemType::Enum));
@@ -1176,7 +1176,7 @@ impl DocFolder for Cache {
11761176

11771177
if pushed { self.stack.pop().unwrap(); }
11781178
if parent_pushed { self.parent_stack.pop().unwrap(); }
1179-
self.privmod = orig_privmod;
1179+
self.stripped_mod = orig_stripped_mod;
11801180
self.parent_is_trait_impl = orig_parent_is_trait_impl;
11811181
return ret;
11821182
}
@@ -1233,15 +1233,12 @@ impl Context {
12331233

12341234
// render the crate documentation
12351235
let mut work = vec!((self, item));
1236-
loop {
1237-
match work.pop() {
1238-
Some((mut cx, item)) => cx.item(item, |cx, item| {
1239-
work.push((cx.clone(), item));
1240-
})?,
1241-
None => break,
1242-
}
1243-
}
12441236

1237+
while let Some((mut cx, item)) = work.pop() {
1238+
cx.item(item, |cx, item| {
1239+
work.push((cx.clone(), item))
1240+
})?
1241+
}
12451242
Ok(())
12461243
}
12471244

@@ -1296,87 +1293,80 @@ impl Context {
12961293
layout::render(&mut writer, &cx.layout, &page,
12971294
&Sidebar{ cx: cx, item: it },
12981295
&Item{ cx: cx, item: it })?;
1296+
12991297
} else {
13001298
let mut url = repeat("../").take(cx.current.len())
13011299
.collect::<String>();
1302-
match cache().paths.get(&it.def_id) {
1303-
Some(&(ref names, _)) => {
1304-
for name in &names[..names.len() - 1] {
1305-
url.push_str(name);
1306-
url.push_str("/");
1307-
}
1308-
url.push_str(&item_path(it));
1309-
layout::redirect(&mut writer, &url)?;
1300+
if let Some(&(ref names, _)) = cache().paths.get(&it.def_id) {
1301+
for name in &names[..names.len() - 1] {
1302+
url.push_str(name);
1303+
url.push_str("/");
13101304
}
1311-
None => {}
1305+
url.push_str(&item_path(it));
1306+
layout::redirect(&mut writer, &url)?;
13121307
}
13131308
}
13141309
writer.flush()
13151310
}
13161311

1317-
// Private modules may survive the strip-private pass if they
1318-
// contain impls for public types. These modules can also
1312+
// Stripped modules survive the rustdoc passes (i.e. `strip-private`)
1313+
// if they contain impls for public types. These modules can also
13191314
// contain items such as publicly reexported structures.
13201315
//
13211316
// External crates will provide links to these structures, so
1322-
// these modules are recursed into, but not rendered normally (a
1323-
// flag on the context).
1317+
// these modules are recursed into, but not rendered normally
1318+
// (a flag on the context).
13241319
if !self.render_redirect_pages {
1325-
self.render_redirect_pages = self.ignore_private_item(&item);
1320+
self.render_redirect_pages = self.maybe_ignore_item(&item);
13261321
}
13271322

1328-
match item.inner {
1323+
if item.is_mod() {
13291324
// modules are special because they add a namespace. We also need to
13301325
// recurse into the items of the module as well.
1331-
clean::ModuleItem(..) => {
1332-
let name = item.name.as_ref().unwrap().to_string();
1333-
let mut item = Some(item);
1334-
self.recurse(name, |this| {
1335-
let item = item.take().unwrap();
1336-
let joint_dst = this.dst.join("index.html");
1337-
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1338-
try_err!(render(dst, this, &item, false), &joint_dst);
1339-
1340-
let m = match item.inner {
1341-
clean::ModuleItem(m) => m,
1342-
_ => unreachable!()
1343-
};
1344-
1345-
// render sidebar-items.js used throughout this module
1346-
{
1347-
let items = this.build_sidebar_items(&m);
1348-
let js_dst = this.dst.join("sidebar-items.js");
1349-
let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
1350-
try_err!(write!(&mut js_out, "initSidebarItems({});",
1351-
as_json(&items)), &js_dst);
1352-
}
1326+
let name = item.name.as_ref().unwrap().to_string();
1327+
let mut item = Some(item);
1328+
self.recurse(name, |this| {
1329+
let item = item.take().unwrap();
1330+
let joint_dst = this.dst.join("index.html");
1331+
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1332+
try_err!(render(dst, this, &item, false), &joint_dst);
13531333

1354-
for item in m.items {
1355-
f(this,item);
1356-
}
1357-
Ok(())
1358-
})
1359-
}
1334+
let m = match item.inner {
1335+
clean::StrippedItem(box clean::ModuleItem(m)) |
1336+
clean::ModuleItem(m) => m,
1337+
_ => unreachable!()
1338+
};
13601339

1361-
// Things which don't have names (like impls) don't get special
1362-
// pages dedicated to them.
1363-
_ if item.name.is_some() => {
1364-
let joint_dst = self.dst.join(&item_path(&item));
1340+
// render sidebar-items.js used throughout this module
1341+
{
1342+
let items = this.build_sidebar_items(&m);
1343+
let js_dst = this.dst.join("sidebar-items.js");
1344+
let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
1345+
try_err!(write!(&mut js_out, "initSidebarItems({});",
1346+
as_json(&items)), &js_dst);
1347+
}
13651348

1366-
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1367-
try_err!(render(dst, self, &item, true), &joint_dst);
1349+
for item in m.items {
1350+
f(this,item);
1351+
}
13681352
Ok(())
1369-
}
1353+
})
1354+
} else if item.name.is_some() {
1355+
let joint_dst = self.dst.join(&item_path(&item));
13701356

1371-
_ => Ok(())
1357+
let dst = try_err!(File::create(&joint_dst), &joint_dst);
1358+
try_err!(render(dst, self, &item, true), &joint_dst);
1359+
Ok(())
1360+
} else {
1361+
Ok(())
13721362
}
13731363
}
13741364

13751365
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc>> {
13761366
// BTreeMap instead of HashMap to get a sorted output
13771367
let mut map = BTreeMap::new();
13781368
for item in &m.items {
1379-
if self.ignore_private_item(item) { continue }
1369+
if self.maybe_ignore_item(item) { continue }
13801370

13811371
let short = shortty(item).to_static_str();
13821372
let myname = match item.name {
@@ -1394,27 +1384,18 @@ impl Context {
13941384
return map;
13951385
}
13961386

1397-
fn ignore_private_item(&self, it: &clean::Item) -> bool {
1387+
fn maybe_ignore_item(&self, it: &clean::Item) -> bool {
13981388
match it.inner {
1389+
clean::StrippedItem(..) => true,
13991390
clean::ModuleItem(ref m) => {
1400-
(m.items.is_empty() &&
1401-
it.doc_value().is_none() &&
1402-
it.visibility != Some(hir::Public)) ||
1403-
(self.passes.contains("strip-private") && it.visibility != Some(hir::Public))
1404-
}
1405-
clean::PrimitiveItem(..) => it.visibility != Some(hir::Public),
1391+
it.doc_value().is_none() && m.items.is_empty() && it.visibility != Some(hir::Public)
1392+
},
14061393
_ => false,
14071394
}
14081395
}
14091396
}
14101397

14111398
impl<'a> Item<'a> {
1412-
fn ismodule(&self) -> bool {
1413-
match self.item.inner {
1414-
clean::ModuleItem(..) => true, _ => false
1415-
}
1416-
}
1417-
14181399
/// Generate a url appropriate for an `href` attribute back to the source of
14191400
/// this item.
14201401
///
@@ -1495,6 +1476,7 @@ impl<'a> Item<'a> {
14951476

14961477
impl<'a> fmt::Display for Item<'a> {
14971478
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1479+
debug_assert!(!self.item.is_stripped());
14981480
// Write the breadcrumb trail header for the top
14991481
write!(fmt, "\n<h1 class='fqn'><span class='in-band'>")?;
15001482
match self.item.inner {
@@ -1516,7 +1498,7 @@ impl<'a> fmt::Display for Item<'a> {
15161498
};
15171499
if !is_primitive {
15181500
let cur = &self.cx.current;
1519-
let amt = if self.ismodule() { cur.len() - 1 } else { cur.len() };
1501+
let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() };
15201502
for (i, component) in cur.iter().enumerate().take(amt) {
15211503
write!(fmt, "<a href='{}index.html'>{}</a>::<wbr>",
15221504
repeat("../").take(cur.len() - i - 1)
@@ -1575,15 +1557,12 @@ impl<'a> fmt::Display for Item<'a> {
15751557
}
15761558

15771559
fn item_path(item: &clean::Item) -> String {
1578-
match item.inner {
1579-
clean::ModuleItem(..) => {
1580-
format!("{}/index.html", item.name.as_ref().unwrap())
1581-
}
1582-
_ => {
1583-
format!("{}.{}.html",
1584-
shortty(item).to_static_str(),
1585-
*item.name.as_ref().unwrap())
1586-
}
1560+
if item.is_mod() {
1561+
format!("{}/index.html", item.name.as_ref().unwrap())
1562+
} else {
1563+
format!("{}.{}.html",
1564+
shortty(item).to_static_str(),
1565+
*item.name.as_ref().unwrap())
15871566
}
15881567
}
15891568

@@ -1626,7 +1605,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
16261605
document(w, cx, item)?;
16271606

16281607
let mut indices = (0..items.len()).filter(|i| {
1629-
!cx.ignore_private_item(&items[*i])
1608+
!cx.maybe_ignore_item(&items[*i])
16301609
}).collect::<Vec<usize>>();
16311610

16321611
// the order of item types in the listing
@@ -1670,6 +1649,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
16701649
let mut curty = None;
16711650
for &idx in &indices {
16721651
let myitem = &items[idx];
1652+
if myitem.is_stripped() {
1653+
continue;
1654+
}
16731655

16741656
let myty = Some(shortty(myitem));
16751657
if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) {
@@ -2146,6 +2128,7 @@ fn render_assoc_item(w: &mut fmt::Formatter,
21462128
where_clause = WhereClause(g))
21472129
}
21482130
match item.inner {
2131+
clean::StrippedItem(..) => Ok(()),
21492132
clean::TyMethodItem(ref m) => {
21502133
method(w, item, m.unsafety, hir::Constness::NotConst,
21512134
m.abi, &m.generics, &m.self_, &m.decl, link)
@@ -2540,6 +2523,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
25402523
assoc_type(w, item, bounds, default.as_ref(), link)?;
25412524
write!(w, "</code></h4>\n")?;
25422525
}
2526+
clean::StrippedItem(..) => return Ok(()),
25432527
_ => panic!("can't make docs for trait item with name {:?}", item.name)
25442528
}
25452529

‎src/librustdoc/passes.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use clean::Item;
2121
use plugins;
2222
use fold;
2323
use fold::DocFolder;
24+
use fold::FoldItem::Strip;
2425

2526
/// Strip items marked `#[doc(hidden)]`
2627
pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
@@ -45,12 +46,10 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
4546
..i
4647
});
4748
}
48-
_ => {
49-
return None;
50-
}
49+
clean::ModuleItem(..) => return Strip(i).fold(),
50+
_ => return None,
5151
}
5252
}
53-
5453
self.fold_item_recur(i)
5554
}
5655
}
@@ -125,6 +124,7 @@ struct Stripper<'a> {
125124
impl<'a> fold::DocFolder for Stripper<'a> {
126125
fn fold_item(&mut self, i: Item) -> Option<Item> {
127126
match i.inner {
127+
clean::StrippedItem(..) => return Some(i),
128128
// These items can all get re-exported
129129
clean::TypedefItem(..) | clean::StaticItem(..) |
130130
clean::StructItem(..) | clean::EnumItem(..) |
@@ -153,8 +153,11 @@ impl<'a> fold::DocFolder for Stripper<'a> {
153153
}
154154
}
155155

156-
// handled below
157-
clean::ModuleItem(..) => {}
156+
clean::ModuleItem(..) => {
157+
if i.def_id.is_local() && i.visibility != Some(hir::Public) {
158+
return Strip(self.fold_item_recur(i).unwrap()).fold()
159+
}
160+
}
158161

159162
// trait impls for private items should be stripped
160163
clean::ImplItem(clean::Impl{
@@ -165,7 +168,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
165168
}
166169
}
167170
// handled in the `strip-priv-imports` pass
168-
clean::ExternCrateItem(..) | clean::ImportItem(_) => {}
171+
clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
169172

170173
clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
171174

@@ -187,7 +190,6 @@ impl<'a> fold::DocFolder for Stripper<'a> {
187190

188191
// implementations of traits are always public.
189192
clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
190-
191193
// Struct variant fields have inherited visibility
192194
clean::VariantItem(clean::Variant {
193195
kind: clean::StructVariant(..)
@@ -202,19 +204,17 @@ impl<'a> fold::DocFolder for Stripper<'a> {
202204
self.fold_item_recur(i)
203205
};
204206

205-
i.and_then(|i| {
206-
match i.inner {
207-
// emptied modules/impls have no need to exist
208-
clean::ModuleItem(ref m)
209-
if m.items.is_empty() &&
210-
i.doc_value().is_none() => None,
211-
clean::ImplItem(ref i) if i.items.is_empty() => None,
212-
_ => {
213-
self.retained.insert(i.def_id);
214-
Some(i)
215-
}
207+
i.and_then(|i| { match i.inner {
208+
// emptied modules/impls have no need to exist
209+
clean::ModuleItem(ref m)
210+
if m.items.is_empty() &&
211+
i.doc_value().is_none() => None,
212+
clean::ImplItem(ref i) if i.items.is_empty() => None,
213+
_ => {
214+
self.retained.insert(i.def_id);
215+
Some(i)
216216
}
217-
})
217+
}})
218218
}
219219
}
220220

‎src/librustdoc/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ impl Collector {
431431
// compiler failures are test failures
432432
should_panic: testing::ShouldPanic::No,
433433
},
434-
testfn: testing::DynTestFn(Box::new(move|| {
434+
testfn: testing::DynTestFn(box move|| {
435435
runtest(&test,
436436
&cratename,
437437
cfgs,
@@ -442,7 +442,7 @@ impl Collector {
442442
as_test_harness,
443443
compile_fail,
444444
&opts);
445-
}))
445+
})
446446
});
447447
}
448448

‎src/test/auxiliary/reexp_stripped.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 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+
pub use private::Quz;
12+
pub use hidden::Bar;
13+
14+
mod private {
15+
pub struct Quz;
16+
}
17+
18+
#[doc(hidden)]
19+
pub mod hidden {
20+
pub struct Bar;
21+
}

‎src/test/rustdoc/redirect.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2016 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:reexp_stripped.rs
12+
// build-aux-docs
13+
// ignore-cross-compile
14+
15+
extern crate reexp_stripped;
16+
17+
pub trait Foo {}
18+
19+
// @has redirect/index.html
20+
// @has - '//code' 'pub use reexp_stripped::Bar'
21+
// @has - '//code/a' 'Bar'
22+
// @has reexp_stripped/hidden/struct.Bar.html
23+
// @has - '//p/a' '../../reexp_stripped/struct.Bar.html'
24+
// @has 'reexp_stripped/struct.Bar.html'
25+
#[doc(no_inline)]
26+
pub use reexp_stripped::Bar;
27+
impl Foo for Bar {}
28+
29+
// @has redirect/index.html
30+
// @has - '//code' 'pub use reexp_stripped::Quz'
31+
// @has - '//code/a' 'Quz'
32+
// @has reexp_stripped/private/struct.Quz.html
33+
// @has - '//p/a' '../../reexp_stripped/struct.Quz.html'
34+
// @has 'reexp_stripped/struct.Quz.html'
35+
#[doc(no_inline)]
36+
pub use reexp_stripped::Quz;
37+
impl Foo for Quz {}
38+
39+
mod private_no_inline {
40+
pub struct Qux;
41+
impl ::Foo for Qux {}
42+
}
43+
44+
// @has redirect/index.html
45+
// @has - '//code' 'pub use private_no_inline::Qux'
46+
// @!has - '//code/a' 'Qux'
47+
#[doc(no_inline)]
48+
pub use private_no_inline::Qux;

0 commit comments

Comments
 (0)
Please sign in to comment.