diff --git a/doc/rustdoc.md b/doc/rustdoc.md index b31e82d00ff..39fc03bca0d 100644 --- a/doc/rustdoc.md +++ b/doc/rustdoc.md @@ -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 ;` where `` 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`. diff --git a/mk/tests.mk b/mk/tests.mk index 4dd87b99441..1a56c008ccb 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -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 \ diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index 5a2b74e8021..c1763c37bb5 100644 --- a/src/libextra/arc.rs +++ b/src/libextra/arc.rs @@ -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 RWArc { * # 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(&self, blk: |v: RWWriteMode| -> U) -> U { diff --git a/src/libextra/future.rs b/src/libextra/future.rs index eb61b7781f1..cb82c1abe1e 100644 --- a/src/libextra/future.rs +++ b/src/libextra/future.rs @@ -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()) * ``` diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs index 1182d526fa4..cb9e53dc69e 100644 --- a/src/libextra/glob.rs +++ b/src/libextra/glob.rs @@ -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. diff --git a/src/libextra/hex.rs b/src/libextra/hex.rs index 83dcc412f57..380476dc4bc 100644 --- a/src/libextra/hex.rs +++ b/src/libextra/hex.rs @@ -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); diff --git a/src/libextra/lru_cache.rs b/src/libextra/lru_cache.rs index ff8748e1946..e1cb54ae452 100644 --- a/src/libextra/lru_cache.rs +++ b/src/libextra/lru_cache.rs @@ -17,6 +17,8 @@ //! # Example //! //! ```rust +//! use extra::lru_cache::LruCache; +//! //! let mut cache: LruCache = LruCache::new(2); //! cache.put(1, 10); //! cache.put(2, 20); diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 1546e9ca59c..57a7f38696d 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -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 ... * }) * }) * ``` diff --git a/src/libextra/url.rs b/src/libextra/url.rs index 13b87b97309..79886273a15 100644 --- a/src/libextra/url.rs +++ b/src/libextra/url.rs @@ -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 { diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index dd921fb9e93..1111be5f417 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -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 { - 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 + } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b0ff224badb..5c3d3484657 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -27,7 +27,7 @@ use clean::Clean; pub struct DocContext { crate: ast::Crate, - tycx: middle::ty::ctxt, + tycx: Option, 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, 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(); diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 513144ad731..6fd83af3b2e 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -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, } +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 diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 3645161ee1c..3d9a0a73e57 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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 { - 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 { match matches.opt_str("r") { Some(~"rust") => Ok(rust_input(input, matches)), Some(~"json") => json_input(input), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs new file mode 100644 index 00000000000..9462f8118ba --- /dev/null +++ b/src/librustdoc/test.rs @@ -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 or the MIT license +// , 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) { + 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, + 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 { + 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; + } +} diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 15dbc68b2ea..03ab85918c7 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -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) -> 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); } } diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 38deaf2dbcb..a7e502be32e 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -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 diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index c2dc7506105..05aab2f9570 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -49,7 +49,9 @@ pub unsafe fn bump_box_refcount(t: @T) { forget(t); } * # Example * * ```rust - * let v: &[u8] = transmute("L"); + * use std::cast; + * + * let v: &[u8] = unsafe { cast::transmute("L") }; * assert!(v == [76u8]); * ``` */ diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index 30324d9bc60..33d5d48ebdc 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -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::::new(); //! drop(chan); //! port.recv(); //! ``` diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index 4d6b540f2a5..bbd4cfea78d 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -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)]; diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs index 1a4e9226ee8..2ecae8e85d0 100644 --- a/src/libstd/condition.rs +++ b/src/libstd/condition.rs @@ -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 Condition { /// ```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(&self, inner: 'a || -> V) -> V { let _g = Guard { cond: self.cond }; diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index b4f30311753..3bbf8031fff 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -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 { 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 { 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) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 537b5de1b4a..bd0b9e08b7c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -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::("127.0.0.1:8080").unwrap(); let mut socket = TcpStream::connect(addr).unwrap(); socket.write(bytes!("GET / HTTP/1.0\n\n")); diff --git a/src/libstd/io/signal.rs b/src/libstd/io/signal.rs index c568a19dfa2..00d84e22c25 100644 --- a/src/libstd/io/signal.rs +++ b/src/libstd/io/signal.rs @@ -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 { diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 5fb64ab3d09..9d4a72509e7 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -17,7 +17,7 @@ and create ports which will receive notifications after a period of time. # Example -```rust +```rust,ignore use std::io::Timer; diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index f16e9b53929..5ace24dbbee 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -218,8 +218,8 @@ pub trait Iterator { /// # 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 { /// # 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 { /// let mut sum = 0; /// for x in it { /// if x > 5 { - /// break; + /// continue; /// } /// sum += x; /// } @@ -391,14 +393,16 @@ pub trait Iterator { /// # 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 { /// /// ```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 { /// ```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 { /// # 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 { /// # 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 { /// # 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 { /// # 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)); diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs index 69f1bfe9395..652aa4d8198 100644 --- a/src/libstd/local_data.rs +++ b/src/libstd/local_data.rs @@ -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])); ``` */ diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 1605dcebf1a..dbe8b3247c0 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -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!(...)); } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 4eef3323403..2cb7d527618 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -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] diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 1668019409e..1f01c26ad76 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -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] diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index c8c2ea8af81..0f81a5faac8 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -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(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); diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 53948dc8309..6488595ea4f 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -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()); ``` */ diff --git a/src/libstd/rand/distributions/gamma.rs b/src/libstd/rand/distributions/gamma.rs index ae7ff99af92..36acae9133c 100644 --- a/src/libstd/rand/distributions/gamma.rs +++ b/src/libstd/rand/distributions/gamma.rs @@ -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); /// } /// ``` diff --git a/src/libstd/rand/distributions/mod.rs b/src/libstd/rand/distributions/mod.rs index dd882f051d3..f13f840df40 100644 --- a/src/libstd/rand/distributions/mod.rs +++ b/src/libstd/rand/distributions/mod.rs @@ -98,10 +98,10 @@ pub struct Weighted { /// 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)); /// } /// } /// ``` diff --git a/src/libstd/rand/distributions/normal.rs b/src/libstd/rand/distributions/normal.rs index a779f4f6066..8b769c113c9 100644 --- a/src/libstd/rand/distributions/normal.rs +++ b/src/libstd/rand/distributions/normal.rs @@ -123,7 +123,7 @@ impl IndependentSample 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) /// } /// ``` diff --git a/src/libstd/rand/distributions/range.rs b/src/libstd/rand/distributions/range.rs index db9cefa4d79..fc6cdde162d 100644 --- a/src/libstd/rand/distributions/range.rs +++ b/src/libstd/rand/distributions/range.rs @@ -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); /// } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index e3929501e19..76bb6723a2e 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -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: 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::()); /// rng.reseed([5, 6, 7, 8]); /// println!("{}", rng.gen::()); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 5f98a34520c..2f5ef932a18 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -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"); /// ``` diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 487f6749e3e..97d4c2f6d1b 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -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 { /// # Example /// /// ```rust - /// use std::vec; - /// /// let mut v = [-5, 4, 1, -3, 2]; /// /// v.sort();