Skip to content

Commit 3d365f6

Browse files
committed
rustdoc: interpret all leading feature attributes in examples as crate attributes
This makes it possible to write `#![feature(foo)]` in doc tests.
1 parent 809a554 commit 3d365f6

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

src/doc/trpl/documentation.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,17 @@ fn main() {
237237
}
238238
```
239239

240-
Here's the full algorithm:
241-
242-
1. Given a code block, if it does not contain `fn main()`, it is wrapped in
243-
`fn main() { your_code }`
244-
2. Given that result, if it contains no `extern crate` directives but it also
245-
contains the name of the crate being tested, then `extern crate <name>` is
246-
injected at the top.
247-
3. Some common allow attributes are added for documentation examples at the top.
240+
Here's the full algorithm rustdoc uses to postprocess examples:
241+
242+
1. Any leading `#![foo]` attributes are left intact as crate attributes.
243+
2. Some common `allow` attributes are inserted, including
244+
`unused_variables`, `unused_assignments`, `unused_mut`,
245+
`unused_attributes`, and `dead_code`. Small examples often trigger
246+
these lints.
247+
3. If the example does not contain `extern crate`, then `extern crate
248+
<mycrate>;` is inserted.
249+
2. Finally, if the example does not contain `fn main`, the remainder of the
250+
text is wrapped in `fn main() { your_code }`
248251

249252
Sometimes, this isn't enough, though. For example, all of these code samples
250253
with `///` we've been talking about? The raw text:

src/librustdoc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ extern crate rustc_back;
5151
extern crate serialize;
5252
extern crate syntax;
5353
extern crate "test" as testing;
54+
extern crate unicode;
5455
#[macro_use] extern crate log;
5556

5657
extern crate "serialize" as rustc_serialize; // used by deriving

src/librustdoc/test.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,14 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
219219
}
220220

221221
pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String {
222+
let (crate_attrs, everything_else) = partition_source(s);
223+
222224
let mut prog = String::new();
225+
226+
// First push any outer attributes from the example, assuming they
227+
// are intended to be crate attributes.
228+
prog.push_str(&crate_attrs);
229+
223230
if lints {
224231
prog.push_str(r"
225232
#![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:
240247
}
241248
}
242249
if dont_insert_main || s.contains("fn main") {
243-
prog.push_str(s);
250+
prog.push_str(&everything_else);
244251
} else {
245252
prog.push_str("fn main() {\n ");
246-
prog.push_str(&s.replace("\n", "\n "));
253+
prog.push_str(&everything_else.replace("\n", "\n "));
247254
prog.push_str("\n}");
248255
}
249256

257+
info!("final test program: {}", prog);
258+
250259
return prog
251260
}
252261

262+
fn partition_source(s: &str) -> (String, String) {
263+
use unicode::str::UnicodeStr;
264+
265+
let mut after_header = false;
266+
let mut before = String::new();
267+
let mut after = String::new();
268+
269+
for line in s.lines() {
270+
let trimline = StrExt::trim(line);
271+
let header = trimline.is_whitespace() ||
272+
trimline.starts_with("#![feature");
273+
if !header || after_header {
274+
after_header = true;
275+
after.push_str(line);
276+
after.push_str("\n");
277+
} else {
278+
before.push_str(line);
279+
before.push_str("\n");
280+
}
281+
}
282+
283+
return (before, after);
284+
}
285+
253286
pub struct Collector {
254287
pub tests: Vec<testing::TestDescAndFn>,
255288
names: Vec<String>,

0 commit comments

Comments
 (0)