auto merge of #11120 : alexcrichton/rust/rustdoc-test, r=brson

This commit adds a `--test` flag to rustdoc to expose the ability to test code examples in doc strings. This work by using sundown's `lang` attribute to figure out how a code block should be tested. The format for this is:

```
1. ```rust
2. ```rust,ignore
3. ```rust,notest
4. ```rust,should_fail
```

Where `rust` means that rustdoc will attempt to test is, `ignore` means that it will not execute the test but it will compile it, `notest` means that rustdoc completely ignores it, and `should_fail` means that the test should fail. This commit also leverages `extra::test` for the testing harness in order to allow parallelization and whatnot.

I have fixed all existing code examples in libstd and libextra, but I have not made a pass through the crates in order to change code blocks to testable code blocks.

It may also be a questionable decision to require opting-in to a testable code block.

Finally, I kept our sugar in the doc suite to omit lines starting with `#` in documentation but still process them during tests.

Closes #2925
This commit is contained in:
bors 2013-12-23 09:16:37 -08:00
commit d9c06586f2
38 changed files with 662 additions and 169 deletions

View File

@ -85,3 +85,92 @@ javascript and a statically-generated search index. No special web server is
required for the search.
[sundown]: https://github.com/vmg/sundown/
# Testing the Documentation
`rustdoc` has support for testing code examples which appear in the
documentation. This is helpful for keeping code examples up to date with the
source code.
To test documentation, the `--test` argument is passed to rustdoc:
~~~
rustdoc --test crate.rs
~~~
## Defining tests
Rust documentation currently uses the markdown format, and code blocks can refer
to any piece of code-related documentation, which isn't always rust. Because of
this, only code blocks with the language of "rust" will be considered for
testing.
~~~
```rust
// This is a testable code block
```
```
// This is not a testable code block
```
// This is not a testable code block (4-space indent)
~~~
In addition to only testing "rust"-language code blocks, there are additional
specifiers that can be used to dictate how a code block is tested:
~~~
```rust,ignore
// This code block is ignored by rustdoc, but is passed through to the test
// harness
```
```rust,should_fail
// This code block is expected to generate a failure
```
~~~
Rustdoc also supplies some extra sugar for helping with some tedious
documentation examples. If a line is prefixed with a `#` character, then the
line will not show up in the HTML documentation, but it will be used when
testing the code block.
~~~
```rust
# // showing 'fib' in this documentation would just be tedious and detracts from
# // what's actualy being documented.
# fn fib(n: int) { n + 2 }
do spawn { fib(200); }
```
~~~
The documentation online would look like `do spawn { fib(200); }`, but when
testing this code, the `fib` function will be included (so it can compile).
## Running tests (advanced)
Running tests often requires some special configuration to filter tests, find
libraries, or try running ignored examples. The testing framework that rustdoc
uses is build on `extra::test`, which is also used when you compile crates with
rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness
with the `--test-args` flag.
~~~
// Only run tests containing 'foo' in their name
rustdoc --test lib.rs --test-args 'foo'
// See what's possible when running tests
rustdoc --test lib.rs --test-args '--help'
// Run all ignored tests
rustdoc --test lib.rs --test-args '--ignored'
~~~
When testing a library, code examples will often show how functions are used,
and this code often requires `use`-ing paths from the crate. To accomodate this,
rustdoc will implicitly add `extern mod <crate>;` where `<crate>` is the name of
the crate being tested to the top of each code example. This means that rustdoc
must be able to find a compiled version of the library crate being tested. Extra
search paths may be added via the `-L` flag to `rustdoc`.

View File

@ -15,6 +15,7 @@
# The names of crates that must be tested
TEST_TARGET_CRATES = std extra rustuv
TEST_DOC_CRATES = std extra
TEST_HOST_CRATES = rustpkg rustc rustdoc syntax
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
@ -281,6 +282,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
@ -303,6 +305,10 @@ check-stage$(1)-T-$(2)-H-$(3)-crates-exec: \
endif
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec: \
$$(foreach crate,$$(TEST_DOC_CRATES), \
check-stage$(1)-T-$(2)-H-$(3)-doc-$$(crate)-exec)
check-stage$(1)-T-$(2)-H-$(3)-doc-exec: \
$$(foreach docname,$$(DOC_TEST_NAMES), \
check-stage$(1)-T-$(2)-H-$(3)-doc-$$(docname)-exec)
@ -734,6 +740,26 @@ $(foreach host,$(CFG_HOST), \
$(foreach docname,$(DOC_TEST_NAMES), \
$(eval $(call DEF_RUN_DOC_TEST,$(stage),$(target),$(host),$(docname)))))))
CRATE_DOC_LIB-std = $(STDLIB_CRATE)
CRATE_DOC_LIB-extra = $(EXTRALIB_CRATE)
define DEF_CRATE_DOC_TEST
check-stage$(1)-T-$(2)-H-$(2)-doc-$(3)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(2),doc-$(3))
$$(call TEST_OK_FILE,$(1),$(2),$(2),doc-$(3)): \
$$(TEST_SREQ$(1)_T_$(2)_H_$(2)) \
$$(HBIN$(1)_H_$(2))/rustdoc$$(X_$(2))
@$$(call E, run doc-$(3) [$(2)])
$$(Q)$$(HBIN$(1)_H_$(2))/rustdoc$$(X_$(2)) --test \
$$(CRATE_DOC_LIB-$(3)) && touch $$@
endef
$(foreach host,$(CFG_HOST), \
$(foreach stage,$(STAGES), \
$(foreach crate,$(TEST_DOC_CRATES), \
$(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(host),$(crate))))))
######################################################################
# Extracting tests for docs
@ -762,6 +788,7 @@ $(foreach host,$(CFG_HOST), \
TEST_GROUPS = \
crates \
$(foreach crate,$(TEST_CRATES),$(crate)) \
$(foreach crate,$(TEST_DOC_CRATES),doc-$(crate)) \
rpass \
rpass-full \
rfail \

View File

@ -18,18 +18,19 @@
* With simple pipes, without Arc, a copy would have to be made for each task.
*
* ```rust
* extern mod std;
* use extra::arc;
* let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random());
* let shared_numbers=arc::Arc::new(numbers);
* use extra::arc::Arc;
* use std::{rand, vec};
*
* do 10.times {
* let (port, chan) = stream();
* let numbers = vec::from_fn(100, |i| (i as f32) * rand::random());
* let shared_numbers = Arc::new(numbers);
*
* for _ in range(0, 10) {
* let (port, chan) = Chan::new();
* chan.send(shared_numbers.clone());
*
* do spawn {
* let shared_numbers=port.recv();
* let local_numbers=shared_numbers.get();
* let shared_numbers = port.recv();
* let local_numbers = shared_numbers.get();
*
* // Work with the local numbers
* }
@ -448,15 +449,18 @@ impl<T:Freeze + Send> RWArc<T> {
* # Example
*
* ```rust
* do arc.write_downgrade |mut write_token| {
* do write_token.write_cond |state, condvar| {
* ... exclusive access with mutable state ...
* }
* use extra::arc::RWArc;
*
* let arc = RWArc::new(1);
* arc.write_downgrade(|mut write_token| {
* write_token.write_cond(|state, condvar| {
* // ... exclusive access with mutable state ...
* });
* let read_token = arc.downgrade(write_token);
* do read_token.read |state| {
* ... shared access with immutable state ...
* }
* }
* read_token.read(|state| {
* // ... shared access with immutable state ...
* });
* })
* ```
*/
pub fn write_downgrade<U>(&self, blk: |v: RWWriteMode<T>| -> U) -> U {

View File

@ -15,9 +15,10 @@
* # Example
*
* ```rust
* use extra::future::Future;
* # fn fib(n: uint) -> uint {42};
* # fn make_a_sandwich() {};
* let mut delayed_fib = extra::future::spawn (|| fib(5000) );
* let mut delayed_fib = do Future::spawn { fib(5000) };
* make_a_sandwich();
* println!("fib(5000) = {}", delayed_fib.get())
* ```

View File

@ -53,8 +53,10 @@ pub struct GlobIterator {
/// `puppies.jpg` and `hamsters.gif`:
///
/// ```rust
/// use extra::glob::glob;
///
/// for path in glob("/media/pictures/*.jpg") {
/// println(path.to_str());
/// println!("{}", path.display());
/// }
/// ```
///
@ -188,21 +190,23 @@ enum MatchResult {
impl Pattern {
/**
* This function compiles Unix shell style patterns: `?` matches any single character,
* `*` matches any (possibly empty) sequence of characters and `[...]` matches any character
* inside the brackets, unless the first character is `!` in which case it matches any
* character except those between the `!` and the `]`. Character sequences can also specify
* ranges of characters, as ordered by Unicode, so e.g. `[0-9]` specifies any character
* between 0 and 9 inclusive.
* This function compiles Unix shell style patterns: `?` matches any single
* character, `*` matches any (possibly empty) sequence of characters and
* `[...]` matches any character inside the brackets, unless the first
* character is `!` in which case it matches any character except those
* between the `!` and the `]`. Character sequences can also specify ranges
* of characters, as ordered by Unicode, so e.g. `[0-9]` specifies any
* character between 0 and 9 inclusive.
*
* The metacharacters `?`, `*`, `[`, `]` can be matched by using brackets (e.g. `[?]`).
* When a `]` occurs immediately following `[` or `[!` then it is interpreted as
* being part of, rather then ending, the character set, so `]` and NOT `]` can be
* matched by `[]]` and `[!]]` respectively. The `-` character can be specified inside a
* character sequence pattern by placing it at the start or the end, e.g. `[abc-]`.
* The metacharacters `?`, `*`, `[`, `]` can be matched by using brackets
* (e.g. `[?]`). When a `]` occurs immediately following `[` or `[!` then
* it is interpreted as being part of, rather then ending, the character
* set, so `]` and NOT `]` can be matched by `[]]` and `[!]]` respectively.
* The `-` character can be specified inside a character sequence pattern by
* placing it at the start or the end, e.g. `[abc-]`.
*
* When a `[` does not have a closing `]` before the end of the string then the `[` will
* be treated literally.
* When a `[` does not have a closing `]` before the end of the string then
* the `[` will be treated literally.
*/
pub fn new(pattern: &str) -> Pattern {
@ -229,7 +233,8 @@ impl Pattern {
match chars.slice_from(i + 3).position_elem(&']') {
None => (),
Some(j) => {
let cs = parse_char_specifiers(chars.slice(i + 2, i + 3 + j));
let chars = chars.slice(i + 2, i + 3 + j);
let cs = parse_char_specifiers(chars);
tokens.push(AnyExcept(cs));
i += j + 4;
continue;
@ -292,6 +297,8 @@ impl Pattern {
* # Example
*
* ```rust
* use extra::glob::Pattern;
*
* assert!(Pattern::new("c?t").matches("cat"));
* assert!(Pattern::new("k[!e]tteh").matches("kitteh"));
* assert!(Pattern::new("d*g").matches("doog"));
@ -509,7 +516,7 @@ impl MatchOptions {
*
* This function always returns this value:
*
* ```rust
* ```rust,ignore
* MatchOptions {
* case_sensitive: true,
* require_literal_separator: false.

View File

@ -28,7 +28,6 @@ impl<'a> ToHex for &'a [u8] {
* # Example
*
* ```rust
* extern mod extra;
* use extra::hex::ToHex;
*
* fn main () {
@ -71,12 +70,11 @@ impl<'a> FromHex for &'a str {
* This converts a string literal to hexadecimal and back.
*
* ```rust
* extern mod extra;
* use extra::hex::{FromHex, ToHex};
* use std::str;
*
* fn main () {
* let hello_str = "Hello, World".to_hex();
* let hello_str = "Hello, World".as_bytes().to_hex();
* println!("{}", hello_str);
* let bytes = hello_str.from_hex().unwrap();
* println!("{:?}", bytes);

View File

@ -17,6 +17,8 @@
//! # Example
//!
//! ```rust
//! use extra::lru_cache::LruCache;
//!
//! let mut cache: LruCache<int, int> = LruCache::new(2);
//! cache.put(1, 10);
//! cache.put(2, 20);

View File

@ -568,13 +568,16 @@ impl RWLock {
* # Example
*
* ```rust
* use extra::sync::RWLock;
*
* let lock = RWLock::new();
* lock.write_downgrade(|mut write_token| {
* write_token.write_cond(|condvar| {
* ... exclusive access ...
* // ... exclusive access ...
* });
* let read_token = lock.downgrade(write_token);
* read_token.read(|| {
* ... shared access ...
* // ... shared access ...
* })
* })
* ```

View File

@ -26,6 +26,8 @@ use std::uint;
/// # Example
///
/// ```rust
/// use extra::url::{Url, UserInfo};
///
/// let url = Url { scheme: ~"https",
/// user: Some(UserInfo { user: ~"username", pass: None }),
/// host: ~"example.com",
@ -388,8 +390,10 @@ fn query_from_str(rawquery: &str) -> Query {
* # Example
*
* ```rust
* use extra::url;
*
* let query = ~[(~"title", ~"The Village"), (~"north", ~"52.91"), (~"west", ~"4.10")];
* println(query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
* println(url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
* ```
*/
pub fn query_to_str(query: &Query) -> ~str {

View File

@ -1147,13 +1147,17 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
id: ast::NodeId) -> Type {
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let tycx = match cx.tycx {
Some(tycx) => tycx,
// If we're extracting tests, this return value doesn't matter.
None => return Bool
};
debug!("searching for {:?} in defmap", id);
let d = match cx.tycx.def_map.find(&id) {
let d = match tycx.def_map.find(&id) {
Some(k) => k,
None => {
let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
debug!("could not find {:?} in defmap (`{}`)", id,
syntax::ast_map::node_id_to_str(ctxt.tycx.items, id, ctxt.sess.intr()));
syntax::ast_map::node_id_to_str(tycx.items, id, cx.sess.intr()));
fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
}
};
@ -1182,7 +1186,7 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
if ast_util::is_local(def_id) {
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
} else {
let fqn = csearch::get_item_path(cx.tycx, def_id);
let fqn = csearch::get_item_path(tycx, def_id);
let fqn = fqn.move_iter().map(|i| {
match i {
ast_map::path_mod(id) |
@ -1203,6 +1207,11 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
}
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
let dm = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.def_map;
dm.find(&id).map(|&d| ast_util::def_id_of_def(d))
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
match cx.tycx {
Some(tcx) => {
tcx.def_map.find(&id).map(|&d| ast_util::def_id_of_def(d))
}
None => None
}
}

View File

@ -27,7 +27,7 @@ use clean::Clean;
pub struct DocContext {
crate: ast::Crate,
tycx: middle::ty::ctxt,
tycx: Option<middle::ty::ctxt>,
sess: driver::session::Session
}
@ -78,17 +78,13 @@ fn get_ast_and_resolve(cpath: &Path,
} = phase_3_run_analysis_passes(sess, &crate);
debug!("crate: {:?}", crate);
return (DocContext { crate: crate, tycx: ty_cx, sess: sess },
return (DocContext { crate: crate, tycx: Some(ty_cx), sess: sess },
CrateAnalysis { exported_items: exported_items });
}
pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Crate, CrateAnalysis) {
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs);
let ctxt = @ctxt;
debug!("defmap:");
for (k, v) in ctxt.tycx.def_map.iter() {
debug!("{:?}: {:?}", k, v);
}
local_data::set(super::ctxtkey, ctxt);
let v = @mut RustdocVisitor::new();

View File

@ -22,9 +22,12 @@
//! // ... something using html
//! ```
use std::cast;
use std::fmt;
use std::libc;
use std::io;
use std::libc;
use std::str;
use std::unstable::intrinsics;
use std::vec;
/// A unit struct which has the `fmt::Default` trait implemented. When
@ -41,8 +44,10 @@ static MKDEXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
type sd_markdown = libc::c_void; // this is opaque to us
// this is a large struct of callbacks we don't use
type sd_callbacks = [libc::size_t, ..26];
struct sd_callbacks {
blockcode: extern "C" fn(*buf, *buf, *buf, *libc::c_void),
other: [libc::size_t, ..25],
}
struct html_toc_data {
header_count: libc::c_int,
@ -56,6 +61,11 @@ struct html_renderopt {
link_attributes: Option<extern "C" fn(*buf, *buf, *libc::c_void)>,
}
struct my_opaque {
opt: html_renderopt,
dfltblk: extern "C" fn(*buf, *buf, *buf, *libc::c_void),
}
struct buf {
data: *u8,
size: libc::size_t,
@ -84,7 +94,28 @@ extern {
}
fn render(w: &mut io::Writer, s: &str) {
pub fn render(w: &mut io::Writer, s: &str) {
extern fn block(ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
unsafe {
let my_opaque: &my_opaque = cast::transmute(opaque);
vec::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
let text = str::from_utf8(text);
let mut lines = text.lines().filter(|l| {
!l.trim().starts_with("#")
});
let text = lines.to_owned_vec().connect("\n");
let buf = buf {
data: text.as_bytes().as_ptr(),
size: text.len() as libc::size_t,
asize: text.len() as libc::size_t,
unit: 0,
};
(my_opaque.dfltblk)(ob, &buf, lang, opaque);
})
}
}
// This code is all lifted from examples/sundown.c in the sundown repo
unsafe {
let ob = bufnew(OUTPUT_UNIT);
@ -100,11 +131,16 @@ fn render(w: &mut io::Writer, s: &str) {
flags: 0,
link_attributes: None,
};
let callbacks: sd_callbacks = [0, ..26];
let mut callbacks: sd_callbacks = intrinsics::init();
sdhtml_renderer(&callbacks, &options, 0);
let opaque = my_opaque {
opt: options,
dfltblk: callbacks.blockcode,
};
callbacks.blockcode = block;
let markdown = sd_markdown_new(extensions, 16, &callbacks,
&options as *html_renderopt as *libc::c_void);
&opaque as *my_opaque as *libc::c_void);
sd_markdown_render(ob, s.as_ptr(), s.len() as libc::size_t, markdown);
@ -118,6 +154,48 @@ fn render(w: &mut io::Writer, s: &str) {
}
}
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
extern fn block(_ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
unsafe {
if text.is_null() || lang.is_null() { return }
let (test, shouldfail, ignore) =
vec::raw::buf_as_slice((*lang).data,
(*lang).size as uint, |lang| {
let s = str::from_utf8(lang);
(s.contains("rust"), s.contains("should_fail"),
s.contains("ignore"))
});
if !test { return }
vec::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
let tests: &mut ::test::Collector = intrinsics::transmute(opaque);
let text = str::from_utf8(text);
let mut lines = text.lines().map(|l| l.trim_chars(&'#'));
let text = lines.to_owned_vec().connect("\n");
tests.add_test(text, ignore, shouldfail);
})
}
}
unsafe {
let ob = bufnew(OUTPUT_UNIT);
let extensions = MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_TABLES |
MKDEXT_FENCED_CODE | MKDEXT_AUTOLINK |
MKDEXT_STRIKETHROUGH;
let callbacks = sd_callbacks {
blockcode: block,
other: intrinsics::init()
};
let tests = tests as *mut ::test::Collector as *libc::c_void;
let markdown = sd_markdown_new(extensions, 16, &callbacks, tests);
sd_markdown_render(ob, doc.as_ptr(), doc.len() as libc::size_t,
markdown);
sd_markdown_free(markdown);
bufrelease(ob);
}
}
impl<'a> fmt::Default for Markdown<'a> {
fn fmt(md: &Markdown<'a>, fmt: &mut fmt::Formatter) {
// This is actually common enough to special-case

View File

@ -47,6 +47,7 @@ pub mod html {
pub mod passes;
pub mod plugins;
pub mod visit_ast;
pub mod test;
pub static SCHEMA_VERSION: &'static str = "0.8.1";
@ -100,6 +101,9 @@ pub fn opts() -> ~[groups::OptGroup] {
optmulti("", "plugins", "space separated list of plugins to also load",
"PLUGINS"),
optflag("", "no-defaults", "don't run the default passes"),
optflag("", "test", "run code examples as tests"),
optmulti("", "test-args", "arguments to pass to the test runner",
"ARGS"),
]
}
@ -114,6 +118,19 @@ pub fn main_args(args: &[~str]) -> int {
return 0;
}
if matches.free.len() == 0 {
println("expected an input file to act on");
return 1;
} if matches.free.len() > 1 {
println("only one input file may be specified");
return 1;
}
let input = matches.free[0].as_slice();
if matches.opt_present("test") {
return test::run(input, &matches);
}
if matches.opt_strs("passes") == ~[~"list"] {
println("Available passes for running rustdoc:");
for &(name, _, description) in PASSES.iter() {
@ -126,7 +143,7 @@ pub fn main_args(args: &[~str]) -> int {
return 0;
}
let (crate, res) = match acquire_input(&matches) {
let (crate, res) = match acquire_input(input, &matches) {
Ok(pair) => pair,
Err(s) => {
println!("input error: {}", s);
@ -157,14 +174,8 @@ pub fn main_args(args: &[~str]) -> int {
/// Looks inside the command line arguments to extract the relevant input format
/// and files and then generates the necessary rustdoc output for formatting.
fn acquire_input(matches: &getopts::Matches) -> Result<Output, ~str> {
if matches.free.len() == 0 {
return Err(~"expected an input file to act on");
} if matches.free.len() > 1 {
return Err(~"only one input file may be specified");
}
let input = matches.free[0].as_slice();
fn acquire_input(input: &str,
matches: &getopts::Matches) -> Result<Output, ~str> {
match matches.opt_str("r") {
Some(~"rust") => Ok(rust_input(input, matches)),
Some(~"json") => json_input(input),

207
src/librustdoc/test.rs Normal file
View File

@ -0,0 +1,207 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::hashmap::HashSet;
use std::local_data;
use std::os;
use std::run;
use std::str;
use extra::tempfile::TempDir;
use extra::getopts;
use extra::test;
use rustc::driver::driver;
use rustc::driver::session;
use syntax::diagnostic;
use syntax::parse;
use core;
use clean;
use clean::Clean;
use fold::DocFolder;
use html::markdown;
use passes;
use visit_ast::RustdocVisitor;
pub fn run(input: &str, matches: &getopts::Matches) -> int {
let parsesess = parse::new_parse_sess(None);
let input = driver::file_input(Path::new(input));
let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice()));
let libs = @mut libs.move_iter().collect();
let sessopts = @session::options {
binary: @"rustdoc",
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: libs,
outputs: ~[session::OutputDylib],
.. (*session::basic_options()).clone()
};
let diagnostic_handler = diagnostic::mk_handler(None);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
let sess = driver::build_session_(sessopts,
parsesess.cm,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter,
span_diagnostic_handler);
let cfg = driver::build_configuration(sess);
let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
let ctx = @core::DocContext {
crate: crate,
tycx: None,
sess: sess,
};
local_data::set(super::ctxtkey, ctx);
let v = @mut RustdocVisitor::new();
v.visit(&ctx.crate);
let crate = v.clean();
let (crate, _) = passes::unindent_comments(crate);
let (crate, _) = passes::collapse_docs(crate);
let mut collector = Collector {
tests: ~[],
names: ~[],
cnt: 0,
libs: libs,
cratename: crate.name.to_owned(),
};
collector.fold_crate(crate);
let args = matches.opt_strs("test-args");
let mut args = args.iter().flat_map(|s| s.words()).map(|s| s.to_owned());
let mut args = args.to_owned_vec();
args.unshift(~"rustdoctest");
test::test_main(args, collector.tests);
0
}
fn runtest(test: &str, cratename: &str, libs: HashSet<Path>) {
let test = maketest(test, cratename);
let parsesess = parse::new_parse_sess(None);
let input = driver::str_input(test);
let sessopts = @session::options {
binary: @"rustdoctest",
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: @mut libs,
outputs: ~[session::OutputExecutable],
debugging_opts: session::prefer_dynamic,
.. (*session::basic_options()).clone()
};
let diagnostic_handler = diagnostic::mk_handler(None);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
let sess = driver::build_session_(sessopts,
parsesess.cm,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter,
span_diagnostic_handler);
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
let out = Some(outdir.path().clone());
let cfg = driver::build_configuration(sess);
driver::compile_input(sess, cfg, &input, &out, &None);
let exe = outdir.path().join("rust_out");
let out = run::process_output(exe.as_str().unwrap(), []);
match out {
None => fail!("couldn't run the test"),
Some(out) => {
if !out.status.success() {
fail!("test executable failed:\n{}",
str::from_utf8(out.error));
}
}
}
}
fn maketest(s: &str, cratename: &str) -> @str {
let mut prog = ~r"
#[deny(warnings)];
#[allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)];
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
";
if s.contains("extra") {
prog.push_str("extern mod extra;\n");
}
if s.contains(cratename) {
prog.push_str(format!("extern mod {};\n", cratename));
}
if s.contains("fn main") {
prog.push_str(s);
} else {
prog.push_str("fn main() {\n");
prog.push_str(s);
prog.push_str("\n}");
}
return prog.to_managed();
}
pub struct Collector {
priv tests: ~[test::TestDescAndFn],
priv names: ~[~str],
priv libs: @mut HashSet<Path>,
priv cnt: uint,
priv cratename: ~str,
}
impl Collector {
pub fn add_test(&mut self, test: &str, ignore: bool, should_fail: bool) {
let test = test.to_owned();
let name = format!("{}_{}", self.names.connect("::"), self.cnt);
self.cnt += 1;
let libs = (*self.libs).clone();
let cratename = self.cratename.to_owned();
self.tests.push(test::TestDescAndFn {
desc: test::TestDesc {
name: test::DynTestName(name),
ignore: ignore,
should_fail: should_fail,
},
testfn: test::DynTestFn(proc() {
runtest(test, cratename, libs);
}),
});
}
}
impl DocFolder for Collector {
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
let pushed = match item.name {
Some(ref name) if name.len() == 0 => false,
Some(ref name) => { self.names.push(name.to_owned()); true }
None => false
};
match item.doc_value() {
Some(doc) => {
self.cnt = 0;
markdown::find_testable_code(doc, self);
}
None => {}
}
let ret = self.fold_item_recur(item);
if pushed {
self.names.pop();
}
return ret;
}
}

View File

@ -12,11 +12,10 @@
//! usable for clean
use syntax::abi::AbiSet;
use syntax::{ast, ast_map};
use syntax::ast;
use syntax::codemap::Span;
use doctree::*;
use std::local_data;
pub struct RustdocVisitor {
module: Module,
@ -91,15 +90,8 @@ impl RustdocVisitor {
}
fn visit_mod_contents(span: Span, attrs: ~[ast::Attribute], vis:
ast::visibility, id: ast::NodeId, m: &ast::_mod) -> Module {
let am = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.items;
let name = match am.find(&id) {
Some(m) => match m {
&ast_map::node_item(ref it, _) => Some(it.ident),
_ => fail!("mod id mapped to non-item in the ast map")
},
None => None
};
ast::visibility, id: ast::NodeId, m: &ast::_mod,
name: Option<ast::Ident>) -> Module {
let mut om = Module::new(name);
om.view_items = m.view_items.clone();
om.where = span;
@ -117,7 +109,8 @@ impl RustdocVisitor {
match item.node {
ast::item_mod(ref m) => {
om.mods.push(visit_mod_contents(item.span, item.attrs.clone(),
item.vis, item.id, m));
item.vis, item.id, m,
Some(item.ident)));
},
ast::item_enum(ref ed, ref gen) => om.enums.push(visit_enum_def(item, ed, gen)),
ast::item_struct(sd, ref gen) => om.structs.push(visit_struct_def(item, sd, gen)),
@ -182,6 +175,7 @@ impl RustdocVisitor {
}
self.module = visit_mod_contents(crate.span, crate.attrs.clone(),
ast::public, ast::CRATE_NODE_ID, &crate.module);
ast::public, ast::CRATE_NODE_ID,
&crate.module, None);
}
}

View File

@ -51,13 +51,13 @@ let my_string = "Hello, world!";
let my_c_string = my_string.to_c_str();
my_c_string.with_ref(|c_buffer| {
unsafe { puts(c_buffer); }
})
});
// Don't save off the allocation of the C string, the `c_buffer` will be
// deallocated when this block returns!
my_string.with_c_str(|c_buffer| {
unsafe { puts(c_buffer); }
})
});
```
*/
@ -216,7 +216,11 @@ pub trait ToCStr {
/// # Example
///
/// ```rust
/// let s = "PATH".with_c_str(|path| libc::getenv(path))
/// use std::libc;
///
/// let s = "PATH".with_c_str(|path| unsafe {
/// libc::getenv(path)
/// });
/// ```
///
/// # Failure

View File

@ -49,7 +49,9 @@ pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
* # Example
*
* ```rust
* let v: &[u8] = transmute("L");
* use std::cast;
*
* let v: &[u8] = unsafe { cast::transmute("L") };
* assert!(v == [76u8]);
* ```
*/

View File

@ -57,7 +57,7 @@
//!
//! # Example
//!
//! ```rust
//! ```rust,should_fail
//! // Create a simple streaming channel
//! let (port, chan) = Chan::new();
//! do spawn {
@ -81,7 +81,7 @@
//!
//! // The call to recv() will fail!() because the channel has already hung
//! // up (or been deallocated)
//! let (port, chan) = Chan::new();
//! let (port, chan) = Chan::<int>::new();
//! drop(chan);
//! port.recv();
//! ```

View File

@ -25,7 +25,7 @@
//!
//! # Example
//!
//! ```rust
//! ```rust,ignore
//! let (mut p1, c1) = Chan::new();
//! let (mut p2, c2) = Chan::new();
//!
@ -40,6 +40,7 @@
//! assert_eq!(val, 2);
//! }
//! )
//! ```
#[allow(dead_code)];

View File

@ -23,13 +23,17 @@ A condition is declared through the `condition!` macro provided by the compiler:
condition! {
pub my_error: int -> ~str;
}
```
# fn main() {}
```
This macro declares an inner module called `my_error` with one static variable,
`cond` that is a static `Condition` instance. To help understand what the other
parameters are used for, an example usage of this condition would be:
```rust
# condition! { pub my_error: int -> ~str; }
# fn main() {
my_error::cond.trap(|raised_int| {
// the condition `my_error` was raised on, and the value it raised is stored
@ -51,6 +55,8 @@ my_error::cond.trap(|raised_int| {
println(my_error::cond.raise(4)); // prints "oh well"
})
# }
```
Condition handling is useful in cases where propagating errors is either to
@ -99,10 +105,12 @@ impl<T, U> Condition<T, U> {
/// ```rust
/// condition! { my_error: int -> int; }
///
/// # fn main() {
/// let trap = my_error::cond.trap(|error| error + 3);
///
/// // use `trap`'s inside method to register the handler and then run a
/// // block of code with the handler registered
/// # }
/// ```
pub fn trap<'a>(&'a self, h: 'a |T| -> U) -> Trap<'a, T, U> {
let h: Closure = unsafe { ::cast::transmute(h) };
@ -176,10 +184,12 @@ impl<'a, T, U> Trap<'a, T, U> {
/// ```rust
/// condition! { my_error: int -> int; }
///
/// # fn main() {
/// let result = my_error::cond.trap(|error| error + 3).inside(|| {
/// my_error::cond.raise(4)
/// });
/// assert_eq!(result, 7);
/// # }
/// ```
pub fn inside<V>(&self, inner: 'a || -> V) -> V {
let _g = Guard { cond: self.cond };

View File

@ -34,12 +34,12 @@ arguments directly while performing minimal allocations.
Some examples of the `format!` extension are:
```rust
format!("Hello") // => ~"Hello"
format!("Hello, {:s}!", "world") // => ~"Hello, world!"
format!("The number is {:d}", 1) // => ~"The number is 1"
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
format!("{value}", value=4) // => ~"4"
format!("{} {}", 1, 2) // => ~"1 2"
format!("Hello"); // => ~"Hello"
format!("Hello, {:s}!", "world"); // => ~"Hello, world!"
format!("The number is {:d}", 1); // => ~"The number is 1"
format!("{:?}", ~[3, 4]); // => ~"~[3, 4]"
format!("{value}", value=4); // => ~"4"
format!("{} {}", 1, 2); // => ~"1 2"
```
From these, you can see that the first argument is a format string. It is
@ -62,7 +62,7 @@ iterator over the argument. Each time a "next argument" specifier is seen, the
iterator advances. This leads to behavior like this:
```rust
format!("{1} {} {0} {}", 1, 2) // => ~"2 1 1 2"
format!("{1} {} {0} {}", 1, 2); // => ~"2 1 1 2"
```
The internal iterator over the argument has not been advanced by the time the
@ -89,9 +89,9 @@ identifier '=' expression
For example, the following `format!` expressions all use named argument:
```rust
format!("{argument}", argument = "test") // => ~"test"
format!("{name} {}", 1, name = 2) // => ~"2 1"
format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3) // => ~"a 3 ()"
format!("{argument}", argument = "test"); // => ~"test"
format!("{name} {}", 1, name = 2); // => ~"2 1"
format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3); // => ~"a 3 ()"
```
It is illegal to put positional parameters (those without names) after arguments
@ -160,7 +160,11 @@ When implementing a format trait for your own time, you will have to implement a
method of the signature:
```rust
# use std;
# struct T;
# trait SomeName<T> {
fn fmt(value: &T, f: &mut std::fmt::Formatter);
# }
```
Your type will be passed by-reference in `value`, and then the function should
@ -218,7 +222,7 @@ fn main() {
There are a number of related macros in the `format!` family. The ones that are
currently implemented are:
```rust
```rust,ignore
format! // described above
write! // first argument is a &mut io::Writer, the destination
writeln! // same as write but appends a newline
@ -261,9 +265,13 @@ references information on the stack. Under the hood, all of
the related macros are implemented in terms of this. First
off, some example usage is:
```rust
```rust,ignore
use std::fmt;
# fn lol<T>() -> T { fail!() }
# let my_writer: &mut ::std::io::Writer = lol();
# let my_fn: fn(&fmt::Arguments) = lol();
format_args!(fmt::format, "this returns {}", "~str");
format_args!(|args| { fmt::write(my_writer, args) }, "some {}", "args");
format_args!(my_fn, "format {}", "string");
@ -305,7 +313,7 @@ to reference the string value of the argument which was selected upon. As an
example:
```rust
format!("{0, select, other{#}}", "hello") // => ~"hello"
format!("{0, select, other{#}}", "hello"); // => ~"hello"
```
This example is the equivalent of `{0:s}` essentially.
@ -585,7 +593,9 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
///
/// ```rust
/// use std::fmt;
/// let w: &mut io::Writer = ...;
/// use std::io;
///
/// let w = &mut io::stdout() as &mut io::Writer;
/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world");
/// ```
pub fn write(output: &mut io::Writer, args: &Arguments) {
@ -650,8 +660,9 @@ pub unsafe fn write_unsafe(output: &mut io::Writer,
///
/// ```rust
/// use std::fmt;
///
/// let s = format_args!(fmt::format, "Hello, {}!", "world");
/// assert_eq!(s, "Hello, world!");
/// assert_eq!(s, ~"Hello, world!");
/// ```
pub fn format(args: &Arguments) -> ~str {
unsafe { format_unsafe(args.fmt, args.args) }

View File

@ -26,6 +26,10 @@ Some examples of obvious things you might want to do
* Read lines from stdin
```rust
use std::io::buffered::BufferedReader;
use std::io::stdin;
# let _g = ::std::io::ignore_io_error();
let mut stdin = BufferedReader::new(stdin());
for line in stdin.lines() {
print(line);
@ -35,12 +39,18 @@ Some examples of obvious things you might want to do
* Read a complete file
```rust
use std::io::File;
# let _g = ::std::io::ignore_io_error();
let contents = File::open(&Path::new("message.txt")).read_to_end();
```
* Write a line to a file
```rust
use std::io::File;
# let _g = ::std::io::ignore_io_error();
let mut file = File::create(&Path::new("message.txt"));
file.write(bytes!("hello, file!\n"));
```
@ -48,6 +58,10 @@ Some examples of obvious things you might want to do
* Iterate over the lines of a file
```rust
use std::io::buffered::BufferedReader;
use std::io::File;
# let _g = ::std::io::ignore_io_error();
let path = Path::new("message.txt");
let mut file = BufferedReader::new(File::open(&path));
for line in file.lines() {
@ -58,6 +72,10 @@ Some examples of obvious things you might want to do
* Pull the lines of a file into a vector of strings
```rust
use std::io::buffered::BufferedReader;
use std::io::File;
# let _g = ::std::io::ignore_io_error();
let path = Path::new("message.txt");
let mut file = BufferedReader::new(File::open(&path));
let lines: ~[~str] = file.lines().collect();
@ -67,7 +85,11 @@ Some examples of obvious things you might want to do
XXX This needs more improvement: TcpStream constructor taking &str,
`write_str` and `write_line` methods.
```rust
```rust,should_fail
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
# let _g = ::std::io::ignore_io_error();
let addr = from_str::<SocketAddr>("127.0.0.1:8080").unwrap();
let mut socket = TcpStream::connect(addr).unwrap();
socket.write(bytes!("GET / HTTP/1.0\n\n"));

View File

@ -60,11 +60,11 @@ pub enum Signum {
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// use std::io::signal::{Listener, Interrupt};
///
/// let mut listener = Listener::new();
/// listener.register(signal::Interrupt);
/// listener.register(Interrupt);
///
/// do spawn {
/// loop {

View File

@ -17,7 +17,7 @@ and create ports which will receive notifications after a period of time.
# Example
```rust
```rust,ignore
use std::io::Timer;

View File

@ -218,8 +218,8 @@ pub trait Iterator<A> {
/// # Example
///
/// ```rust
/// let a = [100, 200, 300];
/// let mut it = xs.iter().map(|&x|x).peekable();
/// let xs = [100, 200, 300];
/// let mut it = xs.iter().map(|x| *x).peekable();
/// assert_eq!(it.peek().unwrap(), &100);
/// assert_eq!(it.next().unwrap(), 100);
/// assert_eq!(it.next().unwrap(), 200);
@ -338,12 +338,14 @@ pub trait Iterator<A> {
/// # Example
///
/// ```rust
/// use std::iter::count;
///
/// let xs = [2u, 3];
/// let ys = [0u, 1, 0, 1, 2];
/// let mut it = xs.iter().flat_map(|&x| count(0u, 1).take(x));
/// // Check that `it` has the same elements as `ys`
/// let mut i = 0;
/// for x: uint in it {
/// for x in it {
/// assert_eq!(x, ys[i]);
/// i += 1;
/// }
@ -366,7 +368,7 @@ pub trait Iterator<A> {
/// let mut sum = 0;
/// for x in it {
/// if x > 5 {
/// break;
/// continue;
/// }
/// sum += x;
/// }
@ -391,14 +393,16 @@ pub trait Iterator<A> {
/// # Example
///
/// ```rust
///let xs = [1u, 4, 2, 3, 8, 9, 6];
///let sum = xs.iter()
/// .map(|&x| x)
/// .inspect(|&x| debug!("filtering %u", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| debug!("%u made it through", x))
/// .sum();
///println(sum.to_str());
/// use std::iter::AdditiveIterator;
///
/// let xs = [1u, 4, 2, 3, 8, 9, 6];
/// let sum = xs.iter()
/// .map(|&x| x)
/// .inspect(|&x| debug!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| debug!("{} made it through", x))
/// .sum();
/// println(sum.to_str());
/// ```
#[inline]
fn inspect<'r>(self, f: 'r |&A|) -> Inspect<'r, A, Self> {
@ -554,8 +558,8 @@ pub trait Iterator<A> {
///
/// ```rust
/// let a = [1, 2, 3, 4, 5];
/// assert!(a.iter().all(|&x| *x > 0));
/// assert!(!a.iter().all(|&x| *x > 2));
/// assert!(a.iter().all(|x| *x > 0));
/// assert!(!a.iter().all(|x| *x > 2));
/// ```
#[inline]
fn all(&mut self, f: |A| -> bool) -> bool {
@ -571,8 +575,8 @@ pub trait Iterator<A> {
/// ```rust
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert!(it.any(|&x| *x == 3));
/// assert!(!it.any(|&x| *x == 3));
/// assert!(it.any(|x| *x == 3));
/// assert!(!it.any(|x| *x == 3));
/// ```
#[inline]
fn any(&mut self, f: |A| -> bool) -> bool {
@ -618,7 +622,7 @@ pub trait Iterator<A> {
/// # Example
///
/// ```rust
/// let xs = [-3, 0, 1, 5, -10];
/// let xs = [-3i, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
/// ```
#[inline]
@ -642,7 +646,7 @@ pub trait Iterator<A> {
/// # Example
///
/// ```rust
/// let xs = [-3, 0, 1, 5, -10];
/// let xs = [-3i, 0, 1, 5, -10];
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
/// ```
#[inline]
@ -811,6 +815,8 @@ pub trait AdditiveIterator<A> {
/// # Example
///
/// ```rust
/// use std::iter::AdditiveIterator;
///
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().map(|&x| x);
/// assert!(it.sum() == 15);
@ -834,7 +840,7 @@ pub trait MultiplicativeIterator<A> {
/// # Example
///
/// ```rust
/// use std::iter::count;
/// use std::iter::{count, MultiplicativeIterator};
///
/// fn factorial(n: uint) -> uint {
/// count(1u, 1).take_while(|&i| i <= n).product()
@ -907,6 +913,8 @@ pub trait ClonableIterator {
/// # Example
///
/// ```rust
/// use std::iter::{ClonableIterator, count};
///
/// let a = count(1,1).take(1);
/// let mut cy = a.cycle();
/// assert_eq!(cy.next(), Some(1));

View File

@ -29,10 +29,10 @@ local_data_key!(key_int: int)
local_data_key!(key_vector: ~[int])
local_data::set(key_int, 3);
local_data::get(key_int, |opt| assert_eq!(opt, Some(&3)));
local_data::get(key_int, |opt| assert_eq!(opt.map(|x| *x), Some(3)));
local_data::set(key_vector, ~[4]);
local_data::get(key_vector, |opt| assert_eq!(opt, Some(&~[4])));
local_data::get(key_vector, |opt| assert_eq!(*opt.unwrap(), ~[4]));
```
*/

View File

@ -78,7 +78,7 @@ error,hello=warn // turn on global error logging and also warn for hello
Each of these macros will expand to code similar to:
```rust
```rust,ignore
if log_level <= my_module_log_level() {
::std::logging::log(log_level, format!(...));
}

View File

@ -339,7 +339,8 @@ impl Round for f32 {
/// The fractional part of the number, satisfying:
///
/// ```rust
/// assert!(x == trunc(x) + fract(x))
/// let x = 1.65f32;
/// assert!(x == x.trunc() + x.fract())
/// ```
///
#[inline]

View File

@ -357,7 +357,8 @@ impl Round for f64 {
/// The fractional part of the number, satisfying:
///
/// ```rust
/// assert!(x == trunc(x) + fract(x))
/// let x = 1.65f64;
/// assert!(x == x.trunc() + x.fract())
/// ```
///
#[inline]

View File

@ -101,8 +101,7 @@ pub trait Unsigned: Num {}
/// Times trait
///
/// ```rust
/// use num::Times;
/// let ten = 10 as uint;
/// let ten = 10u;
/// let mut accum = 0;
/// ten.times(|| { accum += 1; })
/// ```
@ -176,10 +175,10 @@ pub trait Round {
/// # Example
///
/// ```rust
/// assert_approx_eq!(1.3f32.round(), 1.0);
/// assert_approx_eq!((-1.3f32).round(), -1.0);
/// assert_approx_eq!(1.5f32.round(), 1.0);
/// assert_approx_eq!((-1.5f32).round(), -1.0);
/// assert_approx_eq!(1.3f32.trunc(), 1.0);
/// assert_approx_eq!((-1.3f32).trunc(), -1.0);
/// assert_approx_eq!(1.5f32.trunc(), 1.0);
/// assert_approx_eq!((-1.5f32).trunc(), -1.0);
/// ```
fn trunc(&self) -> Self;
@ -188,10 +187,10 @@ pub trait Round {
/// # Example
///
/// ```rust
/// assert_approx_eq!(1.3f32.round(), 0.3);
/// assert_approx_eq!((-1.3f32).round(), -0.3);
/// assert_approx_eq!(1.5f32.round(), 0.5);
/// assert_approx_eq!((-1.5f32).round(), -0.5);
/// assert_approx_eq!(1.3f32.fract(), 0.3);
/// assert_approx_eq!((-1.3f32).fract(), -0.3);
/// assert_approx_eq!(1.5f32.fract(), 0.5);
/// assert_approx_eq!((-1.5f32).fract(), -0.5);
/// ```
fn fract(&self) -> Self;
}
@ -225,7 +224,9 @@ pub trait Algebraic {
/// # Example
///
/// ```rust
/// let sixteen: float = num::pow(2.0, 4.0);
/// use std::num;
///
/// let sixteen: f64 = num::pow(2.0, 4.0);
/// assert_eq!(sixteen, 16.0);
/// ```
#[inline(always)] pub fn pow<T: Algebraic>(value: T, n: T) -> T { value.pow(&n) }
@ -266,6 +267,8 @@ pub trait Trigonometric {
/// # Example
///
/// ```rust
/// use std::f32;
///
/// let y = 3f32.sqrt();
/// let x = 1f32;
/// assert_approx_eq!(y.atan2(&x), f32::consts::PI / 3f32);

View File

@ -54,12 +54,11 @@ actually operates on the path; it is only intended for display.
```rust
let mut path = Path::new("/tmp/path");
debug!("path: {}", path.display());
println!("path: {}", path.display());
path.set_filename("foo");
path.push("bar");
debug!("new path: {}", path.display());
let b = std::os::path_exists(&path);
debug!("path exists: {}", b);
println!("new path: {}", path.display());
println!("path exists: {}", path.exists());
```
*/

View File

@ -39,7 +39,7 @@ use num;
///
/// fn main() {
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(rand::task_rng());
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// }
/// ```

View File

@ -98,10 +98,10 @@ pub struct Weighted<T> {
/// let wc = WeightedChoice::new(~[Weighted { weight: 2, item: 'a' },
/// Weighted { weight: 4, item: 'b' },
/// Weighted { weight: 1, item: 'c' }]);
/// let rng = rand::task_rng();
/// let mut rng = rand::task_rng();
/// for _ in range(0, 16) {
/// // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
/// println!("{}", wc.ind_sample(rng));
/// println!("{}", wc.ind_sample(&mut rng));
/// }
/// }
/// ```

View File

@ -123,7 +123,7 @@ impl IndependentSample<f64> for Normal {
/// fn main() {
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0);
/// let v = normal.ind_sample(&mut rand::task_rng());
/// let v = log_normal.ind_sample(&mut rand::task_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// }
/// ```

View File

@ -39,10 +39,10 @@ use rand::distributions::{Sample, IndependentSample};
///
/// fn main() {
/// let between = Range::new(10u, 10000u);
/// let rng = rand::task_rng();
/// let mut rng = rand::task_rng();
/// let mut sum = 0;
/// for _ in range(0, 1000) {
/// sum += between.ind_sample(rng);
/// sum += between.ind_sample(&mut rng);
/// }
/// println!("{}", sum);
/// }

View File

@ -64,7 +64,7 @@ use std::rand;
fn main () {
let tuple_ptr = rand::random::<~(f64, char)>();
println!(tuple_ptr)
println!("{:?}", tuple_ptr)
}
```
*/
@ -227,7 +227,7 @@ pub trait Rng {
/// let mut rng = rand::task_rng();
/// let n: uint = rng.gen_range(0u, 10);
/// println!("{}", n);
/// let m: float = rng.gen_range(-40.0, 1.3e5);
/// let m: f64 = rng.gen_range(-40.0, 1.3e5);
/// println!("{}", m);
/// }
/// ```
@ -292,8 +292,10 @@ pub trait Rng {
/// use std::rand::Rng;
///
/// fn main() {
/// println!("{:?}", rand::task_rng().choose_option([1,2,4,8,16,32]));
/// println!("{:?}", rand::task_rng().choose_option([]));
/// let choices = [1, 2, 4, 8, 16, 32];
/// let mut rng = rand::task_rng();
/// println!("{:?}", rng.choose_option(choices));
/// println!("{:?}", rng.choose_option(choices.slice_to(0)));
/// }
/// ```
fn choose_option<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
@ -388,11 +390,10 @@ pub trait SeedableRng<Seed>: Rng {
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::Rng;
/// use std::rand::{Rng, SeedableRng, StdRng};
///
/// fn main() {
/// let mut rng: rand::StdRng = rand::SeedableRng::from_seed(&[1, 2, 3, 4]);
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
/// println!("{}", rng.gen::<f64>());
/// rng.reseed([5, 6, 7, 8]);
/// println!("{}", rng.gen::<f64>());

View File

@ -1458,10 +1458,10 @@ pub trait StrSlice<'a> {
/// let v: ~[(uint, uint)] = "abcXXXabcYYYabc".match_indices("abc").collect();
/// assert_eq!(v, ~[(0,3), (6,9), (12,15)]);
///
/// let v: ~[(uint, uint)] = "1abcabc2".split_str("abc").collect();
/// let v: ~[(uint, uint)] = "1abcabc2".match_indices("abc").collect();
/// assert_eq!(v, ~[(1,4), (4,7)]);
///
/// let v: ~[(uint, uint)] = "ababa".split_str("aba").collect();
/// let v: ~[(uint, uint)] = "ababa".match_indices("aba").collect();
/// assert_eq!(v, ~[(0, 3)]); // only the first `aba`
/// ```
fn match_indices(&self, sep: &'a str) -> MatchesIndexIterator<'a>;
@ -1536,7 +1536,7 @@ pub trait StrSlice<'a> {
/// assert!(" \t\n".is_whitespace());
/// assert!("".is_whitespace());
///
/// assert!( !"abc.is_whitespace());
/// assert!( !"abc".is_whitespace());
/// ```
fn is_whitespace(&self) -> bool;
@ -1606,7 +1606,7 @@ pub trait StrSlice<'a> {
/// let s = "Löwe 老虎 Léopard";
/// assert_eq!(s.slice(0, 1), "L");
///
/// assert_eq!(s.slice(1, 9), "öwe 老"));
/// assert_eq!(s.slice(1, 9), "öwe 老");
///
/// // these will fail:
/// // byte 2 lies within `ö`:
@ -1808,6 +1808,8 @@ pub trait StrSlice<'a> {
/// `.char_indices`.
///
/// ```rust
/// use std::str::CharRange;
///
/// let s = "中华Việt Nam";
/// let mut i = 0u;
/// while i < s.len() {
@ -1949,11 +1951,11 @@ pub trait StrSlice<'a> {
///
/// ```rust
/// let s = "Löwe 老虎 Léopard";
/// let (c, s1) = s.shift_slice_char();
/// let (c, s1) = s.slice_shift_char();
/// assert_eq!(c, 'L');
/// assert_eq!(s1, "öwe 老虎 Léopard");
///
/// let (c, s2) = s1.shift_slice_char();
/// let (c, s2) = s1.slice_shift_char();
/// assert_eq!(c, 'ö');
/// assert_eq!(s2, "we 老虎 Léopard");
/// ```

View File

@ -2174,12 +2174,12 @@ pub trait MutableVector<'a, T> {
/// # Example
///
/// ```rust
/// let mut v = [5, 4, 1, 3, 2];
/// v.sort(|a, b| a.cmp(b));
/// let mut v = [5i, 4, 1, 3, 2];
/// v.sort_by(|a, b| a.cmp(b));
/// assert_eq!(v, [1, 2, 3, 4, 5]);
///
/// // reverse sorting
/// v.sort(|a, b| b.cmp(a));
/// v.sort_by(|a, b| b.cmp(a));
/// assert_eq!(v, [5, 4, 3, 2, 1]);
/// ```
fn sort_by(self, compare: |&T, &T| -> Ordering);
@ -2395,8 +2395,6 @@ pub trait MutableTotalOrdVector<T> {
/// # Example
///
/// ```rust
/// use std::vec;
///
/// let mut v = [-5, 4, 1, -3, 2];
///
/// v.sort();