Skip to content

Commit 805d5f9

Browse files
don't run doctests on private items
1 parent 3bc2ca7 commit 805d5f9

File tree

2 files changed

+68
-11
lines changed

2 files changed

+68
-11
lines changed

src/librustdoc/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ fn main_args(args: &[String]) -> isize {
532532
let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
533533
let resource_suffix = matches.opt_str("resource-suffix");
534534
let enable_minification = !matches.opt_present("disable-minification");
535+
let document_private_items = matches.opt_present("document-private-items");
535536

536537
let edition = matches.opt_str("edition").unwrap_or("2015".to_string());
537538
let edition = match edition.parse() {
@@ -551,7 +552,8 @@ fn main_args(args: &[String]) -> isize {
551552
}
552553
(true, false) => {
553554
return test::run(Path::new(input), cfgs, libs, externs, test_args, crate_name,
554-
maybe_sysroot, display_warnings, linker, edition, cg)
555+
maybe_sysroot, display_warnings, linker, edition, cg,
556+
document_private_items)
555557
}
556558
(false, true) => return markdown::render(Path::new(input),
557559
output.unwrap_or(PathBuf::from("doc")),

src/librustdoc/test.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::env;
1212
use std::ffi::OsString;
1313
use std::io::prelude::*;
1414
use std::io;
15+
use std::mem;
1516
use std::path::{Path, PathBuf};
1617
use std::panic::{self, AssertUnwindSafe};
1718
use std::process::Command;
@@ -41,7 +42,7 @@ use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName};
4142
use errors;
4243
use errors::emitter::ColorConfig;
4344

44-
use clean::Attributes;
45+
use clean::{Attributes, AttributesExt, NestedAttributesExt};
4546
use html::markdown::{self, ErrorCodes, LangString};
4647

4748
#[derive(Clone, Default)]
@@ -51,6 +52,8 @@ pub struct TestOptions {
5152
/// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
5253
/// the default `#![allow(unused)]`.
5354
pub display_warnings: bool,
55+
/// Whether to run doctests on private items.
56+
pub document_private_items: bool,
5457
/// Additional crate-level attributes to add to doctests.
5558
pub attrs: Vec<String>,
5659
}
@@ -65,7 +68,8 @@ pub fn run(input_path: &Path,
6568
display_warnings: bool,
6669
linker: Option<PathBuf>,
6770
edition: Edition,
68-
cg: CodegenOptions)
71+
cg: CodegenOptions,
72+
document_private_items: bool)
6973
-> isize {
7074
let input = config::Input::File(input_path.to_owned());
7175

@@ -124,6 +128,7 @@ pub fn run(input_path: &Path,
124128
});
125129
let mut opts = scrape_test_config(hir_forest.krate());
126130
opts.display_warnings |= display_warnings;
131+
opts.document_private_items |= document_private_items;
127132
let mut collector = Collector::new(
128133
crate_name,
129134
cfgs,
@@ -147,8 +152,9 @@ pub fn run(input_path: &Path,
147152
collector: &mut collector,
148153
map: &map,
149154
codes: ErrorCodes::from(sess.opts.unstable_features.is_nightly_build()),
155+
current_vis: true,
150156
};
151-
hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
157+
hir_collector.visit_testable("".to_string(), &krate.attrs, true, |this| {
152158
intravisit::walk_crate(this, krate);
153159
});
154160
}
@@ -169,9 +175,12 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
169175
let mut opts = TestOptions {
170176
no_crate_inject: false,
171177
display_warnings: false,
178+
document_private_items: false,
172179
attrs: Vec::new(),
173180
};
174181

182+
opts.document_private_items = krate.attrs.lists("doc").has_word("document_private_items");
183+
175184
let test_attrs: Vec<_> = krate.attrs.iter()
176185
.filter(|a| a.check_name("doc"))
177186
.flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new))
@@ -664,12 +673,14 @@ struct HirCollector<'a, 'hir: 'a> {
664673
collector: &'a mut Collector,
665674
map: &'a hir::map::Map<'hir>,
666675
codes: ErrorCodes,
676+
current_vis: bool,
667677
}
668678

669679
impl<'a, 'hir> HirCollector<'a, 'hir> {
670680
fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
671681
name: String,
672682
attrs: &[ast::Attribute],
683+
item_is_pub: bool,
673684
nested: F) {
674685
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs);
675686
if let Some(ref cfg) = attrs.cfg {
@@ -678,6 +689,21 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
678689
}
679690
}
680691

692+
let old_vis = if attrs.has_doc_flag("hidden") {
693+
Some(mem::replace(&mut self.current_vis, false))
694+
} else {
695+
None
696+
};
697+
698+
if !self.collector.opts.document_private_items {
699+
if !(self.current_vis && item_is_pub) {
700+
if let Some(old_vis) = old_vis {
701+
self.current_vis = old_vis;
702+
}
703+
return;
704+
}
705+
}
706+
681707
let has_name = !name.is_empty();
682708
if has_name {
683709
self.collector.names.push(name);
@@ -698,6 +724,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
698724

699725
nested(self);
700726

727+
if let Some(old_vis) = old_vis {
728+
self.current_vis = old_vis;
729+
}
730+
701731
if has_name {
702732
self.collector.names.pop();
703733
}
@@ -710,31 +740,50 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
710740
}
711741

712742
fn visit_item(&mut self, item: &'hir hir::Item) {
743+
let is_public = item.vis.node.is_pub();
744+
713745
let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.node {
714746
self.map.node_to_pretty_string(ty.id)
715747
} else {
716748
item.name.to_string()
717749
};
718750

719-
self.visit_testable(name, &item.attrs, |this| {
751+
let old_vis = if let hir::ItemKind::Mod(..) = item.node {
752+
let old_vis = self.current_vis;
753+
self.current_vis &= is_public;
754+
Some(old_vis)
755+
} else {
756+
None
757+
};
758+
759+
self.visit_testable(name, &item.attrs, is_public, |this| {
720760
intravisit::walk_item(this, item);
721761
});
762+
763+
if let Some(old_vis) = old_vis {
764+
self.current_vis = old_vis;
765+
}
722766
}
723767

724768
fn visit_trait_item(&mut self, item: &'hir hir::TraitItem) {
725-
self.visit_testable(item.ident.to_string(), &item.attrs, |this| {
769+
self.visit_testable(item.ident.to_string(), &item.attrs, true, |this| {
726770
intravisit::walk_trait_item(this, item);
727771
});
728772
}
729773

730774
fn visit_impl_item(&mut self, item: &'hir hir::ImplItem) {
731-
self.visit_testable(item.ident.to_string(), &item.attrs, |this| {
775+
let is_public = item.vis.node.is_pub();
776+
self.visit_testable(item.ident.to_string(), &item.attrs, is_public, |this| {
732777
intravisit::walk_impl_item(this, item);
733778
});
734779
}
735780

736781
fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem) {
737-
self.visit_testable(item.name.to_string(), &item.attrs, |this| {
782+
let is_public = item.vis.node.is_pub();
783+
self.visit_testable(item.name.to_string(),
784+
&item.attrs,
785+
is_public,
786+
|this| {
738787
intravisit::walk_foreign_item(this, item);
739788
});
740789
}
@@ -743,19 +792,25 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
743792
v: &'hir hir::Variant,
744793
g: &'hir hir::Generics,
745794
item_id: ast::NodeId) {
746-
self.visit_testable(v.node.name.to_string(), &v.node.attrs, |this| {
795+
self.visit_testable(v.node.name.to_string(), &v.node.attrs, true, |this| {
747796
intravisit::walk_variant(this, v, g, item_id);
748797
});
749798
}
750799

751800
fn visit_struct_field(&mut self, f: &'hir hir::StructField) {
752-
self.visit_testable(f.ident.to_string(), &f.attrs, |this| {
801+
let is_public = f.vis.node.is_pub();
802+
self.visit_testable(f.ident.to_string(),
803+
&f.attrs,
804+
is_public,
805+
|this| {
753806
intravisit::walk_struct_field(this, f);
754807
});
755808
}
756809

757810
fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef) {
758-
self.visit_testable(macro_def.name.to_string(), &macro_def.attrs, |_| ());
811+
// FIXME(misdreavus): does macro export status surface to us? is it in AccessLevels, does
812+
// its #[macro_export] attribute show up here?
813+
self.visit_testable(macro_def.name.to_string(), &macro_def.attrs, true, |_| ());
759814
}
760815
}
761816

0 commit comments

Comments
 (0)