rustdoc: interpret all leading feature attributes in examples as crate attributes
This makes it possible to write `#![feature(foo)]` in doc tests.
This commit is contained in:
parent
809a554fca
commit
3d365f6a01
@ -237,14 +237,17 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Here's the full algorithm:
|
||||
Here's the full algorithm rustdoc uses to postprocess examples:
|
||||
|
||||
1. Given a code block, if it does not contain `fn main()`, it is wrapped in
|
||||
`fn main() { your_code }`
|
||||
2. Given that result, if it contains no `extern crate` directives but it also
|
||||
contains the name of the crate being tested, then `extern crate <name>` is
|
||||
injected at the top.
|
||||
3. Some common allow attributes are added for documentation examples at the top.
|
||||
1. Any leading `#![foo]` attributes are left intact as crate attributes.
|
||||
2. Some common `allow` attributes are inserted, including
|
||||
`unused_variables`, `unused_assignments`, `unused_mut`,
|
||||
`unused_attributes`, and `dead_code`. Small examples often trigger
|
||||
these lints.
|
||||
3. If the example does not contain `extern crate`, then `extern crate
|
||||
<mycrate>;` is inserted.
|
||||
2. Finally, if the example does not contain `fn main`, the remainder of the
|
||||
text is wrapped in `fn main() { your_code }`
|
||||
|
||||
Sometimes, this isn't enough, though. For example, all of these code samples
|
||||
with `///` we've been talking about? The raw text:
|
||||
|
@ -51,6 +51,7 @@ extern crate rustc_back;
|
||||
extern crate serialize;
|
||||
extern crate syntax;
|
||||
extern crate "test" as testing;
|
||||
extern crate unicode;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
extern crate "serialize" as rustc_serialize; // used by deriving
|
||||
|
@ -219,7 +219,14 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
||||
}
|
||||
|
||||
pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String {
|
||||
let (crate_attrs, everything_else) = partition_source(s);
|
||||
|
||||
let mut prog = String::new();
|
||||
|
||||
// First push any outer attributes from the example, assuming they
|
||||
// are intended to be crate attributes.
|
||||
prog.push_str(&crate_attrs);
|
||||
|
||||
if lints {
|
||||
prog.push_str(r"
|
||||
#![allow(unused_variables, unused_assignments, unused_mut, unused_attributes, dead_code)]
|
||||
@ -240,16 +247,42 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main:
|
||||
}
|
||||
}
|
||||
if dont_insert_main || s.contains("fn main") {
|
||||
prog.push_str(s);
|
||||
prog.push_str(&everything_else);
|
||||
} else {
|
||||
prog.push_str("fn main() {\n ");
|
||||
prog.push_str(&s.replace("\n", "\n "));
|
||||
prog.push_str(&everything_else.replace("\n", "\n "));
|
||||
prog.push_str("\n}");
|
||||
}
|
||||
|
||||
info!("final test program: {}", prog);
|
||||
|
||||
return prog
|
||||
}
|
||||
|
||||
fn partition_source(s: &str) -> (String, String) {
|
||||
use unicode::str::UnicodeStr;
|
||||
|
||||
let mut after_header = false;
|
||||
let mut before = String::new();
|
||||
let mut after = String::new();
|
||||
|
||||
for line in s.lines() {
|
||||
let trimline = StrExt::trim(line);
|
||||
let header = trimline.is_whitespace() ||
|
||||
trimline.starts_with("#![feature");
|
||||
if !header || after_header {
|
||||
after_header = true;
|
||||
after.push_str(line);
|
||||
after.push_str("\n");
|
||||
} else {
|
||||
before.push_str(line);
|
||||
before.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (before, after);
|
||||
}
|
||||
|
||||
pub struct Collector {
|
||||
pub tests: Vec<testing::TestDescAndFn>,
|
||||
names: Vec<String>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user