rustdoc: Add #[doc(test(no_inject_crate))] attribute
So that collections doctests don't automatically fail themselves by injecting `extern crate collections` when they are mostly using the std facade.
This commit is contained in:
parent
3d365f6a01
commit
7770ea706b
3 changed files with 49 additions and 11 deletions
|
@ -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)
|
stripped_filtered_line(l).unwrap_or(l)
|
||||||
}).collect::<Vec<&str>>().connect("\n");
|
}).collect::<Vec<&str>>().connect("\n");
|
||||||
let krate = krate.as_ref().map(|s| &**s);
|
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!("<span class='rusttest'>{}</span>", Escape(&test)));
|
s.push_str(&format!("<span class='rusttest'>{}</span>", Escape(&test)));
|
||||||
});
|
});
|
||||||
s.push_str(&highlight::highlight(&text,
|
s.push_str(&highlight::highlight(&text,
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub fn test(input: &str, libs: SearchPaths, externs: core::Externs,
|
||||||
mut test_args: Vec<String>) -> int {
|
mut test_args: Vec<String>) -> int {
|
||||||
let input_str = load_or_return!(input, 1, 2);
|
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);
|
find_testable_code(&input_str, &mut collector);
|
||||||
test_args.insert(0, "rustdoctest".to_string());
|
test_args.insert(0, "rustdoctest".to_string());
|
||||||
testing::test_main(&test_args, collector.tests);
|
testing::test_main(&test_args, collector.tests);
|
||||||
|
|
|
@ -76,6 +76,8 @@ pub fn run(input: &str,
|
||||||
"rustdoc-test", None)
|
"rustdoc-test", None)
|
||||||
.expect("phase_2_configure_and_expand aborted in rustdoc!");
|
.expect("phase_2_configure_and_expand aborted in rustdoc!");
|
||||||
|
|
||||||
|
let inject_crate = should_inject_crate(&krate);
|
||||||
|
|
||||||
let ctx = core::DocContext {
|
let ctx = core::DocContext {
|
||||||
krate: &krate,
|
krate: &krate,
|
||||||
maybe_typed: core::NotTyped(sess),
|
maybe_typed: core::NotTyped(sess),
|
||||||
|
@ -100,7 +102,8 @@ pub fn run(input: &str,
|
||||||
let mut collector = Collector::new(krate.name.to_string(),
|
let mut collector = Collector::new(krate.name.to_string(),
|
||||||
libs,
|
libs,
|
||||||
externs,
|
externs,
|
||||||
false);
|
false,
|
||||||
|
inject_crate);
|
||||||
collector.fold_crate(krate);
|
collector.fold_crate(krate);
|
||||||
|
|
||||||
test_args.insert(0, "rustdoctest".to_string());
|
test_args.insert(0, "rustdoctest".to_string());
|
||||||
|
@ -110,13 +113,42 @@ pub fn run(input: &str,
|
||||||
0
|
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)]
|
#[allow(deprecated)]
|
||||||
fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
||||||
externs: core::Externs,
|
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
|
// the test harness wants its own `main` & top level functions, so
|
||||||
// never wrap the test in `fn main() { ... }`
|
// 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 input = config::Input::Str(test.to_string());
|
||||||
|
|
||||||
let sessopts = config::Options {
|
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 (crate_attrs, everything_else) = partition_source(s);
|
||||||
|
|
||||||
let mut prog = String::new();
|
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
|
// Don't inject `extern crate std` because it's already injected by the
|
||||||
// compiler.
|
// compiler.
|
||||||
if !s.contains("extern crate") && cratename != Some("std") {
|
if !s.contains("extern crate") && cratename != Some("std") && inject_crate {
|
||||||
match cratename {
|
match cratename {
|
||||||
Some(cratename) => {
|
Some(cratename) => {
|
||||||
if s.contains(cratename) {
|
if s.contains(cratename) {
|
||||||
|
@ -267,7 +300,7 @@ fn partition_source(s: &str) -> (String, String) {
|
||||||
let mut after = String::new();
|
let mut after = String::new();
|
||||||
|
|
||||||
for line in s.lines() {
|
for line in s.lines() {
|
||||||
let trimline = StrExt::trim(line);
|
let trimline = line.trim();
|
||||||
let header = trimline.is_whitespace() ||
|
let header = trimline.is_whitespace() ||
|
||||||
trimline.starts_with("#![feature");
|
trimline.starts_with("#![feature");
|
||||||
if !header || after_header {
|
if !header || after_header {
|
||||||
|
@ -292,11 +325,12 @@ pub struct Collector {
|
||||||
use_headers: bool,
|
use_headers: bool,
|
||||||
current_header: Option<String>,
|
current_header: Option<String>,
|
||||||
cratename: String,
|
cratename: String,
|
||||||
|
inject_crate: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Collector {
|
impl Collector {
|
||||||
pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
|
pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
|
||||||
use_headers: bool) -> Collector {
|
use_headers: bool, inject_crate: bool) -> Collector {
|
||||||
Collector {
|
Collector {
|
||||||
tests: Vec::new(),
|
tests: Vec::new(),
|
||||||
names: Vec::new(),
|
names: Vec::new(),
|
||||||
|
@ -306,11 +340,13 @@ impl Collector {
|
||||||
use_headers: use_headers,
|
use_headers: use_headers,
|
||||||
current_header: None,
|
current_header: None,
|
||||||
cratename: cratename,
|
cratename: cratename,
|
||||||
|
inject_crate: inject_crate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_test(&mut self, test: String,
|
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 name = if self.use_headers {
|
||||||
let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
|
let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
|
||||||
format!("{}_{}", s, self.cnt)
|
format!("{}_{}", s, self.cnt)
|
||||||
|
@ -321,6 +357,7 @@ impl Collector {
|
||||||
let libs = self.libs.clone();
|
let libs = self.libs.clone();
|
||||||
let externs = self.externs.clone();
|
let externs = self.externs.clone();
|
||||||
let cratename = self.cratename.to_string();
|
let cratename = self.cratename.to_string();
|
||||||
|
let inject_crate = self.inject_crate;
|
||||||
debug!("Creating test {}: {}", name, test);
|
debug!("Creating test {}: {}", name, test);
|
||||||
self.tests.push(testing::TestDescAndFn {
|
self.tests.push(testing::TestDescAndFn {
|
||||||
desc: testing::TestDesc {
|
desc: testing::TestDesc {
|
||||||
|
@ -335,7 +372,8 @@ impl Collector {
|
||||||
externs,
|
externs,
|
||||||
should_panic,
|
should_panic,
|
||||||
no_run,
|
no_run,
|
||||||
as_test_harness);
|
as_test_harness,
|
||||||
|
inject_crate);
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue