diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 7ea5bd569e19..cdd8457687ac 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -230,7 +230,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { stripped_filtered_line(l).unwrap_or(l) }).collect::>().connect("\n"); let krate = krate.as_ref().map(|s| &**s); - let test = test::maketest(&test, krate, false, false); + let test = test::maketest(&test, krate, false, false, true); s.push_str(&format!("{}", Escape(&test))); }); s.push_str(&highlight::highlight(&text, diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 09b4915222b3..f3d7ae19f4d3 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -143,7 +143,7 @@ pub fn test(input: &str, libs: SearchPaths, externs: core::Externs, mut test_args: Vec) -> int { let input_str = load_or_return!(input, 1, 2); - let mut collector = Collector::new(input.to_string(), libs, externs, true); + let mut collector = Collector::new(input.to_string(), libs, externs, true, false); find_testable_code(&input_str, &mut collector); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3bd466caf0b7..1b596e65a784 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -76,6 +76,8 @@ pub fn run(input: &str, "rustdoc-test", None) .expect("phase_2_configure_and_expand aborted in rustdoc!"); + let inject_crate = should_inject_crate(&krate); + let ctx = core::DocContext { krate: &krate, maybe_typed: core::NotTyped(sess), @@ -100,7 +102,8 @@ pub fn run(input: &str, let mut collector = Collector::new(krate.name.to_string(), libs, externs, - false); + false, + inject_crate); collector.fold_crate(krate); test_args.insert(0, "rustdoctest".to_string()); @@ -110,13 +113,42 @@ pub fn run(input: &str, 0 } +// Look for #![doc(test(no_crate_inject))], used by crates in the std facade +fn should_inject_crate(krate: &::syntax::ast::Crate) -> bool { + use syntax::attr::AttrMetaMethods; + + let mut inject_crate = true; + + for attr in &krate.attrs { + if attr.check_name("doc") { + for list in attr.meta_item_list().into_iter() { + for attr in list { + if attr.check_name("test") { + for list in attr.meta_item_list().into_iter() { + for attr in list { + if attr.check_name("no_crate_inject") { + inject_crate = false; + } + } + } + } + } + } + } + } + + return inject_crate; +} + #[allow(deprecated)] fn runtest(test: &str, cratename: &str, libs: SearchPaths, externs: core::Externs, - should_panic: bool, no_run: bool, as_test_harness: bool) { + should_panic: bool, no_run: bool, as_test_harness: bool, + inject_crate: bool) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` - let test = maketest(test, Some(cratename), true, as_test_harness); + let test = maketest(test, Some(cratename), true, as_test_harness, + inject_crate); let input = config::Input::Str(test.to_string()); let sessopts = config::Options { @@ -218,7 +250,8 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, } } -pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String { +pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, + dont_insert_main: bool, inject_crate: bool) -> String { let (crate_attrs, everything_else) = partition_source(s); let mut prog = String::new(); @@ -235,7 +268,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: // Don't inject `extern crate std` because it's already injected by the // compiler. - if !s.contains("extern crate") && cratename != Some("std") { + if !s.contains("extern crate") && cratename != Some("std") && inject_crate { match cratename { Some(cratename) => { if s.contains(cratename) { @@ -267,7 +300,7 @@ fn partition_source(s: &str) -> (String, String) { let mut after = String::new(); for line in s.lines() { - let trimline = StrExt::trim(line); + let trimline = line.trim(); let header = trimline.is_whitespace() || trimline.starts_with("#![feature"); if !header || after_header { @@ -292,11 +325,12 @@ pub struct Collector { use_headers: bool, current_header: Option, cratename: String, + inject_crate: bool } impl Collector { pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs, - use_headers: bool) -> Collector { + use_headers: bool, inject_crate: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -306,11 +340,13 @@ impl Collector { use_headers: use_headers, current_header: None, cratename: cratename, + inject_crate: inject_crate } } pub fn add_test(&mut self, test: String, - should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) { + should_panic: bool, no_run: bool, should_ignore: bool, + as_test_harness: bool) { let name = if self.use_headers { let s = self.current_header.as_ref().map(|s| &**s).unwrap_or(""); format!("{}_{}", s, self.cnt) @@ -321,6 +357,7 @@ impl Collector { let libs = self.libs.clone(); let externs = self.externs.clone(); let cratename = self.cratename.to_string(); + let inject_crate = self.inject_crate; debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { @@ -335,7 +372,8 @@ impl Collector { externs, should_panic, no_run, - as_test_harness); + as_test_harness, + inject_crate); })) }); }