Auto merge of #33092 - alexcrichton:rustbuild-docs, r=brson

rustbuild: Run all markdown documentation tests

This commit adds support to rustbuild to run all documentation tests, basically
running `rustdoc --test` over all our documentation.
This commit is contained in:
bors 2016-04-23 05:36:28 -07:00
commit f01bb5ed24
27 changed files with 140 additions and 84 deletions

View File

@ -9,7 +9,8 @@
// except according to those terms.
use std::fs;
use std::path::PathBuf;
use std::path::{PathBuf, Path};
use std::process::Command;
use build::{Build, Compiler};
@ -113,3 +114,42 @@ pub fn compiletest(build: &Build,
build.run(&mut cmd);
}
pub fn docs(build: &Build, compiler: &Compiler) {
let mut stack = vec![build.src.join("src/doc")];
while let Some(p) = stack.pop() {
if p.is_dir() {
stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
continue
}
if p.extension().and_then(|s| s.to_str()) != Some("md") {
continue
}
println!("doc tests for: {}", p.display());
markdown_test(build, compiler, &p);
}
}
pub fn error_index(build: &Build, compiler: &Compiler) {
println!("Testing error-index stage{}", compiler.stage);
let output = testdir(build, compiler.host).join("error-index.md");
build.run(build.tool_cmd(compiler, "error_index_generator")
.arg("markdown")
.arg(&output)
.env("CFG_BUILD", &build.config.build));
markdown_test(build, compiler, &output);
}
fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
let mut cmd = Command::new(build.rustdoc(compiler));
build.add_rustc_lib_path(compiler, &mut cmd);
cmd.arg("--test");
cmd.arg(markdown);
cmd.arg("--test-args").arg(build.flags.args.join(" "));
build.run(&mut cmd);
}

View File

@ -308,6 +308,12 @@ impl Build {
check::compiletest(self, &compiler, target.target,
"compile-fail", "compile-fail-fulldeps")
}
CheckDocs { compiler } => {
check::docs(self, &compiler);
}
CheckErrorIndex { compiler } => {
check::error_index(self, &compiler);
}
DistDocs { stage } => dist::docs(self, stage, target.target),
DistMingw { _dummy } => dist::mingw(self, target.target),

View File

@ -96,6 +96,8 @@ macro_rules! targets {
(check_rpass_valgrind, CheckRPassValgrind { compiler: Compiler<'a> }),
(check_rpass_full, CheckRPassFull { compiler: Compiler<'a> }),
(check_cfail_full, CheckCFailFull { compiler: Compiler<'a> }),
(check_docs, CheckDocs { compiler: Compiler<'a> }),
(check_error_index, CheckErrorIndex { compiler: Compiler<'a> }),
// Distribution targets, creating tarballs
(dist, Dist { stage: u32 }),
@ -341,7 +343,10 @@ impl<'a> Step<'a> {
self.check_rpass_valgrind(compiler),
self.check_rpass_full(compiler),
self.check_cfail_full(compiler),
self.check_error_index(compiler),
self.check_docs(compiler),
self.check_linkcheck(stage),
self.check_tidy(stage),
self.dist(stage),
]
}
@ -383,6 +388,12 @@ impl<'a> Step<'a> {
vec![self.librustc(compiler),
self.tool_compiletest(compiler.stage)]
}
Source::CheckDocs { compiler } => {
vec![self.libstd(compiler)]
}
Source::CheckErrorIndex { compiler } => {
vec![self.libstd(compiler), self.tool_error_index(compiler.stage)]
}
Source::ToolLinkchecker { stage } |
Source::ToolTidy { stage } => {

View File

@ -9,7 +9,7 @@ libraries.
To generate HTML documentation from one source file/crate, do something like:
~~~~
~~~~text
rustdoc --output html-doc/ --output-format html ../src/libstd/path.rs
~~~~
@ -20,7 +20,7 @@ rustdoc --output html-doc/ --output-format html ../src/libstd/path.rs
To generate an HTML version of a doc from Markdown manually, you can do
something like:
~~~~
~~~~text
rustdoc reference.md
~~~~

View File

@ -9,7 +9,7 @@ pattern.
Prefer
```rust
```rust,ignore
use std::io::{File, Open, Write, IoError};
struct Info {
@ -31,7 +31,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
over
```rust
```rust,ignore
use std::io::{File, Open, Write, IoError};
struct Info {

View File

@ -4,7 +4,7 @@
Prefer
```rust
```rust,ignore
impl Foo {
pub fn frob(&self, w: widget) { ... }
}
@ -12,7 +12,7 @@ impl Foo {
over
```rust
```rust,ignore
pub fn frob(foo: &Foo, w: widget) { ... }
```

View File

@ -6,7 +6,7 @@
Prefer
```rust
```rust,ignore
fn foo(b: Bar) {
// use b as owned, directly
}
@ -14,7 +14,7 @@ fn foo(b: Bar) {
over
```rust
```rust,ignore
fn foo(b: &Bar) {
let b = b.clone();
// use b as owned after cloning
@ -33,13 +33,13 @@ needed, not as a way of signaling that copies should be cheap to make.
Prefer
```rust
```rust,ignore
fn foo(b: Bar) -> Bar { ... }
```
over
```rust
```rust,ignore
fn foo(b: Box<Bar>) -> Box<Bar> { ... }
```
@ -56,13 +56,13 @@ it becomes.
Prefer
```rust
```rust,ignore
fn foo<T: Iterator<i32>>(c: T) { ... }
```
over any of
```rust
```rust,ignore
fn foo(c: &[i32]) { ... }
fn foo(c: &Vec<i32>) { ... }
fn foo(c: &SomeOtherCollection<i32>) { ... }
@ -83,14 +83,14 @@ concrete nor overly abstract. See the discussion on
Prefer either of
```rust
```rust,ignore
fn foo(b: &Bar) { ... }
fn foo(b: &mut Bar) { ... }
```
over
```rust
```rust,ignore
fn foo(b: Bar) { ... }
```
@ -101,13 +101,13 @@ ownership is actually needed.
Prefer
```rust
```rust,ignore
fn foo() -> (Bar, Bar)
```
over
```rust
```rust,ignore
fn foo(output: &mut Bar) -> Bar
```
@ -120,7 +120,7 @@ multiple values, it should do so via one of these types.
The primary exception: sometimes a function is meant to modify data
that the caller already owns, for example to re-use a buffer:
```rust
```rust,ignore
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>
```
@ -146,7 +146,7 @@ Choose an argument type that rules out bad inputs.
For example, prefer
```rust
```rust,ignore
enum FooMode {
Mode1,
Mode2,
@ -157,7 +157,7 @@ fn foo(mode: FooMode) { ... }
over
```rust
```rust,ignore
fn foo(mode2: bool, mode3: bool) {
assert!(!mode2 || !mode3);
...

View File

@ -16,7 +16,7 @@ API.
Prefer
```rust
```rust,ignore
struct SearchResult {
found: bool, // item in container?
expected_index: usize // what would the item's index be?
@ -26,13 +26,13 @@ fn binary_search(&self, k: Key) -> SearchResult
```
or
```rust
```rust,ignore
fn binary_search(&self, k: Key) -> (bool, usize)
```
over
```rust
```rust,ignore
fn binary_search(&self, k: Key) -> bool
```
@ -40,13 +40,13 @@ fn binary_search(&self, k: Key) -> bool
Prefer
```rust
```rust,ignore
fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>>
```
over
```rust
```rust,ignore
fn from_utf8_owned(vv: Vec<u8>) -> Option<String>
```

View File

@ -4,7 +4,7 @@
Prefer
```rust
```rust,ignore
fn use_mutex(m: sync::mutex::Mutex<i32>) {
let guard = m.lock();
do_work(guard);
@ -15,7 +15,7 @@ fn use_mutex(m: sync::mutex::Mutex<i32>) {
over
```rust
```rust,ignore
fn use_mutex(m: sync::mutex::Mutex<i32>) {
do_work(m.lock());
// do other work
@ -32,7 +32,7 @@ explicitly `let`-bound to make the lifetime clear. Consider using an explicit
Prefer
```rust
```rust,ignore
let foo = match bar {
Baz => 0,
Quux => 1
@ -41,7 +41,7 @@ let foo = match bar {
over
```rust
```rust,ignore
let foo;
match bar {
Baz => {
@ -60,14 +60,14 @@ conditional expression.
Prefer
```rust
```rust,ignore
let v = s.iter().map(|x| x * 2)
.collect::<Vec<_>>();
```
over
```rust
```rust,ignore
let v: Vec<_> = s.iter().map(|x| x * 2)
.collect();
```
@ -87,7 +87,7 @@ the type by explicit generics instantiation, which is usually more clear.
Use `mut` bindings to signal the span during which a value is mutated:
```rust
```rust,ignore
let mut v = Vec::new();
// push things onto v
let v = v;

View File

@ -4,7 +4,7 @@
Prefer
~~~~
~~~~ignore
match *foo {
X(...) => ...
Y(...) => ...
@ -13,7 +13,7 @@ match *foo {
over
~~~~
~~~~ignore
match foo {
box X(...) => ...
box Y(...) => ...

View File

@ -35,7 +35,7 @@ module hierarchy match, instead.
For all except very short modules (<100 lines) and [tests](../testing/README.md),
place the module `foo` in a separate file, as in:
```rust
```rust,ignore
pub mod foo;
// in foo.rs or foo/mod.rs
@ -45,7 +45,7 @@ pub fn bar() { println!("..."); }
rather than declaring it inline:
```rust
```rust,ignore
pub mod foo {
pub fn bar() { println!("..."); }
/* ... */
@ -67,7 +67,7 @@ On the other hand,
[`io::net`](https://doc.rust-lang.org/std/io/net/)
contains submodules, so it lives in a separate directory:
```
```text
io/mod.rs
io/extensions.rs
io/fs.rs
@ -120,7 +120,7 @@ and
[`BufWriter`](https://doc.rust-lang.org/std/io/struct.BufWriter.html),
but these are re-exported in `io/mod.rs` at the top level of the module:
```rust
```rust,ignore
// libstd/io/mod.rs
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};

View File

@ -19,7 +19,7 @@ workaround; see [newtype for views](../types/newtype.md))
The most important common traits to implement from `std` are:
```rust
```text
Clone, Debug, Hash, Eq
```

View File

@ -4,7 +4,7 @@ The most widespread use of traits is for writing generic functions or types. For
example, the following signature describes a function for consuming any iterator
yielding items of type `A` to produce a collection of `A`:
```rust
```rust,ignore
fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
```
@ -32,7 +32,7 @@ explicitly implement to be used by this generic function.
implementing a trait, it is possible to be precise about places where that
exact type is required or produced. For example, a function
```rust
```rust,ignore
fn binary<T: Trait>(x: T, y: T) -> T
```

View File

@ -6,7 +6,7 @@ Trait objects are useful primarily when _heterogeneous_ collections of objects
need to be treated uniformly; it is the closest that Rust comes to
object-oriented programming.
```rust
```rust,ignore
struct Frame { ... }
struct Button { ... }
struct Label { ... }

View File

@ -4,13 +4,13 @@
Prefer
```rust
```rust,ignore
let w = Widget::new(Small, Round)
```
over
```rust
```rust,ignore
let w = Widget::new(true, false)
```

View File

@ -13,7 +13,7 @@ underlying type.
For example, a `f64` value might be used to represent a quantity in miles or in
kilometers. Using newtypes, we can keep track of the intended interpretation:
```rust
```rust,ignore
struct Miles(pub f64);
struct Kilometers(pub f64);
@ -28,7 +28,7 @@ impl Kilometers {
Once we have separated these two types, we can statically ensure that we do not
confuse them. For example, the function
```rust
```rust,ignore
fn are_we_there_yet(distance_travelled: Miles) -> bool { ... }
```
@ -46,7 +46,7 @@ type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
client, so that the client's view of the return type is roughly `Iterator<(usize,
T)>`. We can do so using the newtype pattern:
```rust
```rust,ignore
struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
impl<T> Iterator<(usize, T)> for MyTransformResult<T> { ... }

View File

@ -35,7 +35,7 @@ be consumed. The follow variant on
[`std::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html)
is one example:
```rust
```rust,ignore
// NOTE: the actual Command API does not use owned Strings;
// this is a simplified version.
@ -94,7 +94,7 @@ methods take and return a mutable borrow of `self`.
By using borrows throughout, `Command` can be used conveniently for both
one-liner and more complex constructions:
```rust
```rust,ignore
// One-liners
Command::new("/bin/cat").arg("file.txt").spawn();
@ -114,7 +114,7 @@ cmd.spawn();
Sometimes builders must transfer ownership when constructing the final type
`T`, meaning that the terminal methods must take `self` rather than `&self`:
```rust
```rust,ignore
// A simplified excerpt from std::thread::Builder
impl ThreadBuilder {
@ -156,7 +156,7 @@ Under the rubric of making easy things easy and hard things possible, _all_
builder methods for a consuming builder should take and returned an owned
`self`. Then client code works as follows:
```rust
```rust,ignore
// One-liners
ThreadBuilder::new().named("my_thread").spawn(proc() { ... });

View File

@ -4,7 +4,7 @@
In Rust, "constructors" are just a convention:
```rust
```rust,ignore
impl<T> Vec<T> {
pub fn new() -> Vec<T> { ... }
}
@ -15,7 +15,7 @@ construct. Combined with the practice of
[fully importing type names](../style/imports.md), this convention leads to
informative but concise construction:
```rust
```rust,ignore
use vec::Vec;
// construct a new vector
@ -29,7 +29,7 @@ than `new`).
Given the `struct`
```rust
```rust,ignore
pub struct Config {
pub color: Color,
pub size: Size,
@ -39,7 +39,7 @@ pub struct Config {
provide a constructor if there are sensible defaults:
```rust
```rust,ignore
impl Config {
pub fn new() -> Config {
Config {
@ -53,7 +53,7 @@ impl Config {
which then allows clients to concisely override using `struct` update syntax:
```rust
```rust,ignore
Config { color: Red, .. Config::new() };
```

View File

@ -2,7 +2,7 @@
### Opening braces always go on the same line.
``` rust
```rust,ignore
fn foo() {
...
}
@ -30,7 +30,7 @@ frob(|x| {
### `match` arms get braces, except for single-line expressions.
``` rust
```rust,ignore
match foo {
bar => baz,
quux => {
@ -42,7 +42,7 @@ match foo {
### `return` statements get semicolons.
``` rust
```rust,ignore
fn foo() {
do_something();
@ -62,7 +62,7 @@ fn foo() {
> One possible rule: a trailing comma should be included whenever the
> closing delimiter appears on a separate line:
```rust
```rust,ignore
Foo { bar: 0, baz: 1 }
Foo {

View File

@ -4,7 +4,7 @@
Use line comments:
``` rust
```rust
// Wait for the main thread to return, and set the process error code
// appropriately.
```
@ -51,7 +51,7 @@ Basically, this means write "Returns" instead of "Return".
For example:
``` rust
```rust,ignore
/// Sets up a default runtime configuration, given compiler-supplied arguments.
///
/// This function will block until the entire pool of M:N schedulers has
@ -80,7 +80,7 @@ For example:
Use inner doc comments _only_ to document crates and file-level modules:
``` rust
```rust,ignore
//! The core library.
//!
//! The core library is a something something...
@ -92,7 +92,7 @@ Rust doesn't have special constructors, only functions that return new
instances. These aren't visible in the automatically generated documentation
for a type, so you should specifically link to them:
``` rust
```rust,ignore
/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///

View File

@ -2,7 +2,7 @@
Terminate `return` statements with semicolons:
``` rust
``` rust,ignore
fn foo(bar: i32) -> Option<i32> {
if some_condition() {
return None;

View File

@ -10,7 +10,7 @@ sections, in order, with a blank space between each:
For example:
```rust
```rust,ignore
// Crates.
extern crate getopts;
extern crate mylib;
@ -40,7 +40,7 @@ as a convenience.
For example:
```rust
```rust,ignore
use option::Option;
use mem;

View File

@ -69,7 +69,7 @@ Names of items within a module should not be prefixed with that module's name:
Prefer
``` rust
```rust,ignore
mod foo {
pub struct Error { ... }
}
@ -77,7 +77,7 @@ mod foo {
over
``` rust
```rust,ignore
mod foo {
pub struct FooError { ... }
}

View File

@ -13,7 +13,7 @@ appropriate. This name is chosen rather than names like `find` or
For a container with keys/indexes of type `K` and elements of type `V`:
```rust
```rust,ignore
// Look up element without failing
fn get(&self, key: K) -> Option<&V>
fn get_mut(&mut self, key: K) -> Option<&mut V>
@ -31,7 +31,7 @@ impl IndexMut<K, V> for Container { ... }
Prefer specific conversion functions like `as_bytes` or `into_vec` whenever
possible. Otherwise, use:
```rust
```rust,ignore
// Extract contents without failing
fn get(&self) -> &V
fn get_mut(&mut self) -> &mut V
@ -40,7 +40,7 @@ fn unwrap(self) -> V
#### Wrappers/Cells around `Copy` data
```rust
```rust,ignore
// Extract contents without failing
fn get(&self) -> V
```
@ -52,7 +52,7 @@ play a special role for failure.
For `Option<V>`:
```rust
```rust,ignore
// Extract contents or fail if not available
fn assert(self) -> V
fn expect(self, &str) -> V
@ -60,7 +60,7 @@ fn expect(self, &str) -> V
For `Result<V, E>`:
```rust
```rust,ignore
// Extract the contents of Ok variant; fail if Err
fn assert(self) -> V

View File

@ -6,7 +6,7 @@
For a container with elements of type `U`, iterator methods should be named:
```rust
```rust,ignore
fn iter(&self) -> T // where T implements Iterator<&U>
fn iter_mut(&mut self) -> T // where T implements Iterator<&mut U>
fn into_iter(self) -> T // where T implements Iterator<U>

View File

@ -8,7 +8,7 @@
* Use spaces around binary operators, including the equals sign in attributes:
``` rust
```rust,ignore
#[deprecated = "Use `bar` instead."]
fn foo(a: usize, b: usize) -> usize {
a + b
@ -17,7 +17,7 @@ fn foo(a: usize, b: usize) -> usize {
* Use a space after colons and commas:
``` rust
```rust,ignore
fn foo(a: Bar);
MyStruct { foo: 3, bar: 4 }
@ -28,7 +28,7 @@ foo(bar, baz);
* Use a space after the opening and before the closing brace for
single line blocks or `struct` expressions:
``` rust
```rust,ignore
spawn(proc() { do_something(); })
Point { x: 0.1, y: 0.3 }
@ -39,7 +39,7 @@ Point { x: 0.1, y: 0.3 }
* For multiline function signatures, each new line should align with the
first parameter. Multiple parameters per line are permitted:
``` rust
```rust,ignore
fn frobnicate(a: Bar, b: Bar,
c: Bar, d: Bar)
-> Bar {
@ -59,7 +59,7 @@ fn foo<T: This,
signatures. However, if the final argument begins a new block, the
contents of the block may begin on a new line, indented one level:
``` rust
```rust,ignore
fn foo_bar(a: Bar, b: Bar,
c: |Bar|) -> Bar {
...
@ -77,7 +77,7 @@ foo_bar(x, y, |z| {
> **[FIXME]** Do we also want to allow the following?
>
> ```rust
> ```rust,ignore
> frobnicate(
> arg1,
> arg2,
@ -92,7 +92,7 @@ foo_bar(x, y, |z| {
> * **[Deprecated]** If you have multiple patterns in a single `match`
> arm, write each pattern on a separate line:
>
> ``` rust
> ```rust,ignore
> match foo {
> bar(_)
> | baz => quux,
@ -110,7 +110,7 @@ Idiomatic code should not use extra whitespace in the middle of a line
to provide alignment.
``` rust
```rust,ignore
// Good
struct Foo {
short: f64,

1
src/rustc/Cargo.lock generated
View File

@ -268,7 +268,6 @@ dependencies = [
"arena 0.0.0",
"log 0.0.0",
"rustc 0.0.0",
"rustc_bitflags 0.0.0",
"syntax 0.0.0",
]