From f0cb0ebc669ade875c05cdef7da341a220d1b522 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 14:35:13 -0800 Subject: [PATCH 1/6] rustdoc: Fixup links to enum variants Pages aren't emitted for enum variants, so whenever we're linking to an enum variant instead link to the parent enum instead. Closes #12289 --- src/librustdoc/html/render.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 11f801550856b..7b67868680f07 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -565,9 +565,16 @@ impl DocFolder for Cache { clean::StructItem(..) | clean::EnumItem(..) | clean::TypedefItem(..) | clean::TraitItem(..) | clean::FunctionItem(..) | clean::ModuleItem(..) | - clean::ForeignFunctionItem(..) | clean::VariantItem(..) => { + clean::ForeignFunctionItem(..) => { self.paths.insert(item.id, (self.stack.clone(), shortty(&item))); } + // link variants to their parent enum because pages aren't emitted + // for each variant + clean::VariantItem(..) => { + let mut stack = self.stack.clone(); + stack.pop(); + self.paths.insert(item.id, (stack, "enum")); + } _ => {} } From 867988c1dc8b17f358a1066160cd9efc9ac1eff5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 21:40:26 -0800 Subject: [PATCH 2/6] rustdoc: Show macros in documentation Any macro tagged with #[macro_export] will be showed in the documentation for that module. This also documents all the existing macros inside of std::macros. Closes #3163 cc #5605 Closes #9954 --- src/librustdoc/clean.rs | 24 ++++- src/librustdoc/doctree.rs | 9 ++ src/librustdoc/html/render.rs | 11 +++ src/librustdoc/passes.rs | 4 +- src/librustdoc/visit_ast.rs | 9 +- src/libstd/lib.rs | 2 +- src/libstd/macros.rs | 172 ++++++++++++++++++++++++++++++++++ 7 files changed, 226 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index 22f9d2f9843b9..c0c146319cbaf 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -181,6 +181,7 @@ pub enum ItemEnum { VariantItem(Variant), ForeignFunctionItem(Function), ForeignStaticItem(Static), + MacroItem(Macro), } #[deriving(Clone, Encodable, Decodable)] @@ -206,7 +207,8 @@ impl Clean for doctree::Module { self.fns.clean(), self.foreigns.clean().concat_vec(), self.mods.clean(), self.typedefs.clean(), self.statics.clean(), self.traits.clean(), - self.impls.clean(), self.view_items.clean()].concat_vec() + self.impls.clean(), self.view_items.clean(), + self.macros.clean()].concat_vec() }) } } @@ -1263,3 +1265,23 @@ fn resolve_def(id: ast::NodeId) -> Option { None => None } } + +#[deriving(Clone, Encodable, Decodable)] +pub struct Macro { + source: ~str, +} + +impl Clean for doctree::Macro { + fn clean(&self) -> Item { + Item { + name: Some(self.name.clean()), + attrs: self.attrs.clean(), + source: self.where.clean(), + visibility: ast::Public.clean(), + id: self.id, + inner: MacroItem(Macro { + source: self.where.to_src(), + }), + } + } +} diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index f1bd3a62e0162..03186c16733a5 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -32,6 +32,7 @@ pub struct Module { impls: ~[Impl], foreigns: ~[ast::ForeignMod], view_items: ~[ast::ViewItem], + macros: ~[Macro], } impl Module { @@ -52,6 +53,7 @@ impl Module { impls : ~[], view_items : ~[], foreigns : ~[], + macros : ~[], } } } @@ -157,6 +159,13 @@ pub struct Impl { id: ast::NodeId, } +pub struct Macro { + name: Ident, + id: ast::NodeId, + attrs: ~[ast::Attribute], + where: Span, +} + pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType { if sd.ctor_id.is_some() { // We are in a tuple-struct diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 7b67868680f07..5299b31ac7bc0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -798,6 +798,7 @@ fn shortty(item: &clean::Item) -> &'static str { clean::VariantItem(..) => "variant", clean::ForeignFunctionItem(..) => "ffi", clean::ForeignStaticItem(..) => "ffs", + clean::MacroItem(..) => "macro", } } @@ -876,6 +877,7 @@ impl<'a> fmt::Show for Item<'a> { clean::StructItem(ref s) => item_struct(fmt.buf, self.item, s), clean::EnumItem(ref e) => item_enum(fmt.buf, self.item, e), clean::TypedefItem(ref t) => item_typedef(fmt.buf, self.item, t), + clean::MacroItem(ref m) => item_macro(fmt.buf, self.item, m), _ => Ok(()) } } @@ -944,6 +946,8 @@ fn item_module(w: &mut Writer, cx: &Context, (_, &clean::ViewItemItem(..)) => Greater, (&clean::ModuleItem(..), _) => Less, (_, &clean::ModuleItem(..)) => Greater, + (&clean::MacroItem(..), _) => Less, + (_, &clean::MacroItem(..)) => Greater, (&clean::StructItem(..), _) => Less, (_, &clean::StructItem(..)) => Greater, (&clean::EnumItem(..), _) => Less, @@ -994,6 +998,7 @@ fn item_module(w: &mut Writer, cx: &Context, clean::VariantItem(..) => "Variants", clean::ForeignFunctionItem(..) => "Foreign Functions", clean::ForeignStaticItem(..) => "Foreign Statics", + clean::MacroItem(..) => "Macros", })); } @@ -1616,3 +1621,9 @@ impl<'a> fmt::Show for Source<'a> { Ok(()) } } + +fn item_macro(w: &mut Writer, it: &clean::Item, + t: &clean::Macro) -> fmt::Result { + if_ok!(write!(w, "
{}
", t.source)); + document(w, it) +} diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 6ebaf6eece82d..2b8f01cfac8ca 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -150,8 +150,8 @@ impl<'a> fold::DocFolder for Stripper<'a> { } clean::ImplItem(..) => {} - // tymethods have no control over privacy - clean::TyMethodItem(..) => {} + // tymethods/macros have no control over privacy + clean::MacroItem(..) | clean::TyMethodItem(..) => {} } let fastreturn = match i.inner { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5bf1aa3e91a6d..ef02d73456721 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -280,7 +280,14 @@ impl<'a> RustdocVisitor<'a> { ast::ItemForeignMod(ref fm) => { om.foreigns.push(fm.clone()); } - _ => (), + ast::ItemMac(ref _m) => { + om.macros.push(Macro { + id: item.id, + attrs: item.attrs.clone(), + name: item.ident, + where: item.span, + }) + } } } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 4452482b7e8ce..d3ddd9ae78380 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -77,7 +77,7 @@ #[cfg(test)] pub use ops = realstd::ops; #[cfg(test)] pub use cmp = realstd::cmp; -mod macros; +pub mod macros; mod rtdeps; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 14ae7c9900c46..49cf10c47cb5a 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -7,8 +7,29 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + +//! Standard library macros +//! +//! This modules contains a set of macros which are exported from the standard +//! library. Each macro is available for use when linking against the standard +//! library. + #[macro_escape]; +/// The standard logging macro +/// +/// This macro will generically log over a provided level (of type u32) with a +/// format!-based argument list. See documentation in `std::fmt` for details on +/// how to use the syntax, and documentation in `std::logging` for info about +/// logging macros. +/// +/// # Example +/// +/// ``` +/// log!(::std::logging::DEBUG, "this is a debug message"); +/// log!(::std::logging::WARN, "this is a warning {}", "message"); +/// log!(6, "this is a custom logging level: {level}", level=6); +/// ``` #[macro_export] macro_rules! log( ($lvl:expr, $($arg:tt)+) => ({ @@ -21,26 +42,73 @@ macro_rules! log( }) ) +/// A convenience macro for logging at the error log level. See `std::logging` +/// for more information. about logging. +/// +/// # Example +/// +/// ``` +/// # let error = 3; +/// error!("the build has failed with error code: {}", error); +/// ``` #[macro_export] macro_rules! error( ($($arg:tt)*) => (log!(1u32, $($arg)*)) ) +/// A convenience macro for logging at the warning log level. See `std::logging` +/// for more information. about logging. +/// +/// # Example +/// +/// ``` +/// # let code = 3; +/// warn!("you may like to know that a process exited with: {}", code); +/// ``` #[macro_export] macro_rules! warn( ($($arg:tt)*) => (log!(2u32, $($arg)*)) ) +/// A convenience macro for logging at the info log level. See `std::logging` +/// for more information. about logging. +/// +/// # Example +/// +/// ``` +/// # let ret = 3; +/// info!("this function is about to return: {}", ret); +/// ``` #[macro_export] macro_rules! info( ($($arg:tt)*) => (log!(3u32, $($arg)*)) ) +/// A convenience macro for logging at the debug log level. See `std::logging` +/// for more information. about logging. +/// +/// # Example +/// +/// ``` +/// debug!("x = {x}, y = {y}", x=10, y=20); +/// ``` #[macro_export] macro_rules! debug( ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(4u32, $($arg)*) }) ) +/// A macro to test whether a log level is enabled for the current module. +/// +/// # Example +/// +/// ``` +/// # struct Point { x: int, y: int } +/// # fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } } +/// if log_enabled!(std::logging::DEBUG) { +/// let x = some_expensive_computation(); +/// debug!("x.x = {}, x.y = {}", x.x, x.y); +/// } +/// ``` #[macro_export] macro_rules! log_enabled( ($lvl:expr) => ({ @@ -49,6 +117,24 @@ macro_rules! log_enabled( }) ) +/// The entry point for failure of rust tasks. +/// +/// This macro is used to inject failure into a rust task, causing the task to +/// unwind and fail entirely. Each task's failure can be reaped as the `~Any` +/// type, and the single-argument form of the `fail!` macro will be the value +/// which is transmitted. +/// +/// The multi-argument form of this macro fails with a string and has the +/// `format!` sytnax for building a string. +/// +/// # Example +/// +/// ```should_fail +/// fail!(); +/// fail!("this is a terrible mistake!"); +/// fail!(4); // fail with the value of 4 to be collected elsewhere +/// fail!("this is a {} {message}", "fancy", message = "message"); +/// ``` #[macro_export] macro_rules! fail( () => ( @@ -70,6 +156,26 @@ macro_rules! fail( }); ) +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `fail!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// # Example +/// +/// ``` +/// // the failure message for these assertions is the stringified value of the +/// // expression given. +/// assert!(true); +/// # fn some_computation() -> bool { true } +/// assert!(some_computation()); +/// +/// // assert with a custom message +/// # let x = true; +/// assert!(x, "x wasn't true!"); +/// # let a = 3; let b = 27; +/// assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` #[macro_export] macro_rules! assert( ($cond:expr) => ( @@ -89,6 +195,18 @@ macro_rules! assert( ); ) +/// Asserts that two expressions are equal to each other, testing equality in +/// both directions. +/// +/// On failure, this macro will print the values of the expressions. +/// +/// # Example +/// +/// ``` +/// let a = 3; +/// let b = 1 + 2; +/// assert_eq!(a, b); +/// ``` #[macro_export] macro_rules! assert_eq( ($given:expr , $expected:expr) => ({ @@ -136,6 +254,16 @@ macro_rules! unimplemented( () => (fail!("not yet implemented")) ) +/// Use the syntax described in `std::fmt` to create a value of type `~str`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10, y = 30); +/// ``` #[macro_export] macro_rules! format( ($($arg:tt)*) => ( @@ -143,6 +271,19 @@ macro_rules! format( ) ) +/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// # #[allow(unused_must_use)]; +/// use std::io::MemWriter; +/// +/// let mut w = MemWriter::new(); +/// write!(&mut w, "test"); +/// write!(&mut w, "formatted {}", "arguments"); +/// ``` #[macro_export] macro_rules! write( ($dst:expr, $($arg:tt)*) => ({ @@ -151,6 +292,8 @@ macro_rules! write( }) ) +/// Equivalent to the `write!` macro, except that a newline is appended after +/// the message is written. #[macro_export] macro_rules! writeln( ($dst:expr, $($arg:tt)*) => ({ @@ -159,16 +302,42 @@ macro_rules! writeln( }) ) +/// Equivalent to the `println!` macro except that a newline is not printed at +/// the end of the message. #[macro_export] macro_rules! print( ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*)) ) +/// Macro for printing to a task's stdout handle. +/// +/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. +/// The syntax of this macro is the same as that used for `format!`. For more +/// information, see `std::fmt` and `std::io::stdio`. +/// +/// # Example +/// +/// ``` +/// println!("hello there!"); +/// println!("format {} arguments", "some"); +/// ``` #[macro_export] macro_rules! println( ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*)) ) +/// Declare a task-local key with a specific type. +/// +/// # Example +/// +/// ``` +/// use std::local_data; +/// +/// local_data_key!(my_integer: int) +/// +/// local_data::set(my_integer, 2); +/// local_data::get(my_integer, |val| println!("{}", val)); +/// ``` #[macro_export] macro_rules! local_data_key( ($name:ident: $ty:ty) => ( @@ -179,6 +348,9 @@ macro_rules! local_data_key( ); ) +/// Helper macro for unwrapping `Result` values while returning early with an +/// error if the value of the expression is `Err`. For more information, see +/// `std::io`. #[macro_export] macro_rules! if_ok( ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) From 6db37bb147c06cddf7ae6a99eb913a5ceaee792b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 21:56:14 -0800 Subject: [PATCH 3/6] rustdoc: Highlight methods jumped to This helps figure out where you actually jumped to, especially if the thing you jumped to is at the very bottom of the page. Closes #9905 --- src/librustdoc/html/static/main.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index e0f4a9c167d2a..8e1876bad0368 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -301,3 +301,5 @@ a { .stability.Stable { border-color: #AEC516; color: #7c8b10; } .stability.Frozen { border-color: #009431; color: #007726; } .stability.Locked { border-color: #0084B6; color: #00668c; } + +:target { background: #FDFFD3; } From 68d576fd345b197e5be08cc9b84201e5897dc729 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 22:31:05 -0800 Subject: [PATCH 4/6] rustdoc: Fix json output and input Turns out a hash map with integer keys isn't serializable to json. Closes #10115 --- src/librustdoc/clean.rs | 7 +++---- src/librustdoc/html/render.rs | 2 +- src/librustdoc/lib.rs | 2 +- src/test/run-make/rustdoc-json/Makefile | 4 ++++ src/test/run-make/rustdoc-json/foo.rs | 25 +++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/test/run-make/rustdoc-json/Makefile create mode 100644 src/test/run-make/rustdoc-json/foo.rs diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index c0c146319cbaf..586323358c241 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -25,7 +25,6 @@ use rustc::metadata::csearch; use rustc::metadata::decoder; use std; -use std::hashmap::HashMap; use doctree; use visit_ast; @@ -68,7 +67,7 @@ impl, U> Clean<~[U]> for syntax::opt_vec::OptVec { pub struct Crate { name: ~str, module: Option, - externs: HashMap, + externs: ~[(ast::CrateNum, ExternalCrate)], } impl<'a> Clean for visit_ast::RustdocVisitor<'a> { @@ -76,9 +75,9 @@ impl<'a> Clean for visit_ast::RustdocVisitor<'a> { use syntax::attr::find_crateid; let cx = local_data::get(super::ctxtkey, |x| *x.unwrap()); - let mut externs = HashMap::new(); + let mut externs = ~[]; cx.sess.cstore.iter_crate_data(|n, meta| { - externs.insert(n, meta.clean()); + externs.push((n, meta.clean())); }); Crate { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5299b31ac7bc0..07ea22d42ecbb 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -305,7 +305,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { krate = folder.fold_crate(krate); } - for (&n, e) in krate.externs.iter() { + for &(n, ref e) in krate.externs.iter() { cache.extern_locations.insert(n, extern_location(e, &cx.dst)); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 2c4d553a39f64..4194f5e472936 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -344,7 +344,7 @@ fn json_output(krate: clean::Crate, res: ~[plugins::PluginJson], }; let crate_json = match json::from_str(crate_json_str) { Ok(j) => j, - Err(_) => fail!("Rust generated JSON is invalid??") + Err(e) => fail!("Rust generated JSON is invalid: {:?}", e) }; json.insert(~"crate", crate_json); diff --git a/src/test/run-make/rustdoc-json/Makefile b/src/test/run-make/rustdoc-json/Makefile new file mode 100644 index 0000000000000..5e6ab4b790ee5 --- /dev/null +++ b/src/test/run-make/rustdoc-json/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk +all: + $(RUSTDOC) -w json -o $(TMPDIR)/doc.json foo.rs + $(RUSTDOC) -o $(TMPDIR)/doc $(TMPDIR)/doc.json diff --git a/src/test/run-make/rustdoc-json/foo.rs b/src/test/run-make/rustdoc-json/foo.rs new file mode 100644 index 0000000000000..818ec1e5eb790 --- /dev/null +++ b/src/test/run-make/rustdoc-json/foo.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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. + +#[crate_id = "foo#0.1"]; + +//! Very docs + +pub mod bar { + + /// So correct + pub mod baz { + /// Much detail + pub fn baz() { } + } + + /// *wow* + pub trait Doge { } +} From cac9107f38c1d28ed263759040b5411b0db47824 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 22:40:08 -0800 Subject: [PATCH 5/6] rustdoc: Clickable links on methods themselves Useful for getting the link to a method or function. Closes #10332 --- src/librustdoc/html/render.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 07ea22d42ecbb..93feef58307d7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1111,7 +1111,7 @@ fn item_trait(w: &mut Writer, it: &clean::Item, if_ok!(write!(w, "\\{\n")); for m in required.iter() { if_ok!(write!(w, " ")); - if_ok!(render_method(w, m.item(), true)); + if_ok!(render_method(w, m.item())); if_ok!(write!(w, ";\n")); } if required.len() > 0 && provided.len() > 0 { @@ -1119,7 +1119,7 @@ fn item_trait(w: &mut Writer, it: &clean::Item, } for m in provided.iter() { if_ok!(write!(w, " ")); - if_ok!(render_method(w, m.item(), true)); + if_ok!(render_method(w, m.item())); if_ok!(write!(w, " \\{ ... \\}\n")); } if_ok!(write!(w, "\\}")); @@ -1133,7 +1133,7 @@ fn item_trait(w: &mut Writer, it: &clean::Item, if_ok!(write!(w, "

", shortty(m.item()), *m.item().name.get_ref())); - if_ok!(render_method(w, m.item(), false)); + if_ok!(render_method(w, m.item())); if_ok!(write!(w, "

")); if_ok!(document(w, m.item())); Ok(()) @@ -1188,16 +1188,12 @@ fn item_trait(w: &mut Writer, it: &clean::Item, }) } -fn render_method(w: &mut Writer, meth: &clean::Item, - withlink: bool) -> fmt::Result { +fn render_method(w: &mut Writer, meth: &clean::Item) -> fmt::Result { fn fun(w: &mut Writer, it: &clean::Item, purity: ast::Purity, - g: &clean::Generics, selfty: &clean::SelfTy, d: &clean::FnDecl, - withlink: bool) -> fmt::Result { - write!(w, "{}fn {withlink, select, - true{{name}} - other{{name}} - }{generics}{decl}", + g: &clean::Generics, selfty: &clean::SelfTy, + d: &clean::FnDecl) -> fmt::Result { + write!(w, "{}fn {name}\ + {generics}{decl}", match purity { ast::UnsafeFn => "unsafe ", _ => "", @@ -1205,15 +1201,14 @@ fn render_method(w: &mut Writer, meth: &clean::Item, ty = shortty(it), name = it.name.get_ref().as_slice(), generics = *g, - decl = Method(selfty, d), - withlink = if withlink {"true"} else {"false"}) + decl = Method(selfty, d)) } match meth.inner { clean::TyMethodItem(ref m) => { - fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink) + fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl) } clean::MethodItem(ref m) => { - fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink) + fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl) } _ => unreachable!() } @@ -1444,7 +1439,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, fn docmeth(w: &mut Writer, item: &clean::Item) -> io::IoResult { if_ok!(write!(w, "

", *item.name.get_ref())); - if_ok!(render_method(w, item, false)); + if_ok!(render_method(w, item)); if_ok!(write!(w, "

\n")); match item.doc_value() { Some(s) => { From 429ef870f67b02664b6ac35b08f3b36b71e8bd00 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Feb 2014 23:11:09 -0800 Subject: [PATCH 6/6] rustdoc: Handle links to reexported items When building up our path cache, we don't plaster over a path which was previously inserted if we're inserting a non-public-item thing. Closes #11678 --- src/librustdoc/html/render.rs | 41 ++++++++++++++++++++++++----------- src/libstd/macros.rs | 7 ++++-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 93feef58307d7..649d5f592c5c5 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -157,6 +157,7 @@ pub struct Cache { priv parent_stack: ~[ast::NodeId], priv search_index: ~[IndexItem], priv privmod: bool, + priv public_items: HashSet, } /// Helper struct to render all source code to HTML pages @@ -231,18 +232,23 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { } // Crawl the crate to build various caches used for the output - let mut cache = Cache { - impls: HashMap::new(), - typarams: HashMap::new(), - paths: HashMap::new(), - traits: HashMap::new(), - implementors: HashMap::new(), - stack: ~[], - parent_stack: ~[], - search_index: ~[], - extern_locations: HashMap::new(), - privmod: false, - }; + let mut cache = local_data::get(::analysiskey, |analysis| { + let public_items = analysis.map(|a| a.public_items.clone()); + let public_items = public_items.unwrap_or(HashSet::new()); + Cache { + impls: HashMap::new(), + typarams: HashMap::new(), + paths: HashMap::new(), + traits: HashMap::new(), + implementors: HashMap::new(), + stack: ~[], + parent_stack: ~[], + search_index: ~[], + extern_locations: HashMap::new(), + privmod: false, + public_items: public_items, + } + }); cache.stack.push(krate.name.clone()); krate = cache.fold_crate(krate); @@ -566,7 +572,16 @@ impl DocFolder for Cache { clean::TypedefItem(..) | clean::TraitItem(..) | clean::FunctionItem(..) | clean::ModuleItem(..) | clean::ForeignFunctionItem(..) => { - self.paths.insert(item.id, (self.stack.clone(), shortty(&item))); + // Reexported items mean that the same id can show up twice in + // the rustdoc ast that we're looking at. We know, however, that + // a reexported item doesn't show up in the `public_items` map, + // so we can skip inserting into the paths map if there was + // already an entry present and we're not a public item. + if !self.paths.contains_key(&item.id) || + self.public_items.contains(&item.id) { + self.paths.insert(item.id, + (self.stack.clone(), shortty(&item))); + } } // link variants to their parent enum because pages aren't emitted // for each variant diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 49cf10c47cb5a..34b33003786e7 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -130,6 +130,7 @@ macro_rules! log_enabled( /// # Example /// /// ```should_fail +/// # #[allow(unreachable_code)]; /// fail!(); /// fail!("this is a terrible mistake!"); /// fail!(4); // fail with the value of 4 to be collected elsewhere @@ -228,13 +229,15 @@ macro_rules! assert_eq( /// # Example /// /// ~~~rust +/// struct Item { weight: uint } +/// /// fn choose_weighted_item(v: &[Item]) -> Item { /// assert!(!v.is_empty()); /// let mut so_far = 0u; /// for item in v.iter() { /// so_far += item.weight; /// if so_far > 100 { -/// return item; +/// return *item; /// } /// } /// // The above loop always returns, so we must hint to the @@ -336,7 +339,7 @@ macro_rules! println( /// local_data_key!(my_integer: int) /// /// local_data::set(my_integer, 2); -/// local_data::get(my_integer, |val| println!("{}", val)); +/// local_data::get(my_integer, |val| println!("{}", val.map(|i| *i))); /// ``` #[macro_export] macro_rules! local_data_key(