about summary refs log tree commit diff
path: root/src/librustdoc/html/render.rs
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-06 17:56:35 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-07 17:54:34 -0700
commit641bca06c82e2fa744e7b14bc45cfa501baf57e6 (patch)
treea058733e05332ad362f2f993b830277600c9db3b /src/librustdoc/html/render.rs
parentfcc89ea5006441350f0275946ff6db84a1118e49 (diff)
downloadrust-641bca06c82e2fa744e7b14bc45cfa501baf57e6.tar.gz
rust-641bca06c82e2fa744e7b14bc45cfa501baf57e6.zip
rustdoc: Link "Trait Implementations" to sources
All methods listed in "Trait Implementations" now hyperlink to the source trait
instead of themselves, allowing easy browsing of the documentation of a trait
method.

Closes #17476
Diffstat (limited to 'src/librustdoc/html/render.rs')
-rw-r--r--src/librustdoc/html/render.rs104
1 files changed, 66 insertions, 38 deletions
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 3796614bcf5..418256d4723 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -62,7 +62,7 @@ use clean;
 use doctree;
 use fold::DocFolder;
 use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace, Stability};
-use html::format::{ConciseStability, TyParamBounds, WhereClause};
+use html::format::{ConciseStability, TyParamBounds, WhereClause, href};
 use html::highlight;
 use html::item_type::ItemType;
 use html::layout;
@@ -137,6 +137,14 @@ pub struct Impl {
     pub stability: Option<clean::Stability>,
 }
 
+impl Impl {
+    fn trait_did(&self) -> Option<ast::DefId> {
+        self.impl_.trait_.as_ref().and_then(|tr| {
+            if let clean::ResolvedPath { did, .. } = *tr {Some(did)} else {None}
+        })
+    }
+}
+
 /// This cache is used to store information about the `clean::Crate` being
 /// rendered in order to provide more useful documentation. This contains
 /// information like all implementors of a trait, all traits a type implements,
@@ -277,7 +285,9 @@ impl fmt::Display for IndexItemFunctionType {
             return write!(f, "null")
         }
 
-        let inputs: Vec<String> = self.inputs.iter().map(|ref t| format!("{}", t)).collect();
+        let inputs: Vec<String> = self.inputs.iter().map(|ref t| {
+            format!("{}", t)
+        }).collect();
         try!(write!(f, "{{\"inputs\":[{}],\"output\":", inputs.connect(",")));
 
         match self.output {
@@ -1780,7 +1790,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         try!(write!(w, "{{\n"));
         for t in &types {
             try!(write!(w, "    "));
-            try!(render_method(w, t));
+            try!(render_method(w, t, MethodLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if types.len() > 0 && required.len() > 0 {
@@ -1788,7 +1798,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &required {
             try!(write!(w, "    "));
-            try!(render_method(w, m));
+            try!(render_method(w, m, MethodLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if required.len() > 0 && provided.len() > 0 {
@@ -1796,7 +1806,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &provided {
             try!(write!(w, "    "));
-            try!(render_method(w, m));
+            try!(render_method(w, m, MethodLink::Anchor));
             try!(write!(w, " {{ ... }}\n"));
         }
         try!(write!(w, "}}"));
@@ -1812,7 +1822,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                     shortty(m),
                     *m.name.as_ref().unwrap(),
                     ConciseStability(&m.stability)));
-        try!(render_method(w, m));
+        try!(render_method(w, m, MethodLink::Anchor));
         try!(write!(w, "</code></h3>"));
         try!(document(w, m));
         Ok(())
@@ -1896,14 +1906,23 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
-fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
+fn render_method(w: &mut fmt::Formatter, meth: &clean::Item,
+                 link: MethodLink) -> fmt::Result {
     fn method(w: &mut fmt::Formatter, it: &clean::Item,
               unsafety: ast::Unsafety, abi: abi::Abi,
               g: &clean::Generics, selfty: &clean::SelfTy,
-              d: &clean::FnDecl) -> fmt::Result {
+              d: &clean::FnDecl, link: MethodLink) -> fmt::Result {
         use syntax::abi::Abi;
 
-        write!(w, "{}{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
+        let name = it.name.as_ref().unwrap();
+        let anchor = format!("#{}.{}", shortty(it), name);
+        let href = match link {
+            MethodLink::Anchor => anchor,
+            MethodLink::GotoSource(did) => {
+                href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
+            }
+        };
+        write!(w, "{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                match unsafety {
                    ast::Unsafety::Unsafe => "unsafe ",
@@ -1913,18 +1932,20 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
                    Abi::Rust => String::new(),
                    a => format!("extern {} ", a.to_string())
                },
-               ty = shortty(it),
-               name = it.name.as_ref().unwrap(),
+               href = href,
+               name = name,
                generics = *g,
                decl = Method(selfty, d),
                where_clause = WhereClause(g))
     }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
-            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
+                   link)
         }
         clean::MethodItem(ref m) => {
-            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
+                   link)
         }
         clean::AssociatedTypeItem(ref bounds, ref default) => {
             assoc_type(w, meth, bounds, default)
@@ -2151,6 +2172,12 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+#[derive(Copy, Clone)]
+enum MethodLink {
+    Anchor,
+    GotoSource(ast::DefId),
+}
+
 fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     match cache().impls.get(&it.def_id) {
         Some(v) => {
@@ -2159,7 +2186,7 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
             if non_trait.len() > 0 {
                 try!(write!(w, "<h2 id='methods'>Methods</h2>"));
                 for i in &non_trait {
-                    try!(render_impl(w, i));
+                    try!(render_impl(w, i, MethodLink::Anchor));
                 }
             }
             if traits.len() > 0 {
@@ -2168,13 +2195,16 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
                 let (derived, manual): (Vec<_>, _) = traits.into_iter()
                     .partition(|i| i.impl_.derived);
                 for i in &manual {
-                    try!(render_impl(w, i));
+                    let did = i.trait_did().unwrap();
+                    try!(render_impl(w, i, MethodLink::GotoSource(did)));
                 }
                 if derived.len() > 0 {
-                    try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
-                                </h3>"));
+                    try!(write!(w, "<h3 id='derived_implementations'>\
+                        Derived Implementations \
+                    </h3>"));
                     for i in &derived {
-                        try!(render_impl(w, i));
+                        let did = i.trait_did().unwrap();
+                        try!(render_impl(w, i, MethodLink::GotoSource(did)));
                     }
                 }
             }
@@ -2184,36 +2214,32 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     Ok(())
 }
 
-fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
+fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink)
+               -> fmt::Result {
     try!(write!(w, "<h3 class='impl'>{}<code>impl{} ",
                 ConciseStability(&i.stability),
                 i.impl_.generics));
-    match i.impl_.polarity {
-        Some(clean::ImplPolarity::Negative) => try!(write!(w, "!")),
-        _ => {}
+    if let Some(clean::ImplPolarity::Negative) = i.impl_.polarity {
+        try!(write!(w, "!"));
     }
-    match i.impl_.trait_ {
-        Some(ref ty) => try!(write!(w, "{} for ", *ty)),
-        None => {}
+    if let Some(ref ty) = i.impl_.trait_ {
+        try!(write!(w, "{} for ", *ty));
     }
-    try!(write!(w, "{}{}</code></h3>", i.impl_.for_, WhereClause(&i.impl_.generics)));
-    match i.dox {
-        Some(ref dox) => {
-            try!(write!(w, "<div class='docblock'>{}</div>",
-                          Markdown(dox)));
-        }
-        None => {}
+    try!(write!(w, "{}{}</code></h3>", i.impl_.for_,
+                WhereClause(&i.impl_.generics)));
+    if let Some(ref dox) = i.dox {
+        try!(write!(w, "<div class='docblock'>{}</div>", Markdown(dox)));
     }
 
-    fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
-                    -> fmt::Result {
+    fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
+                    dox: bool, link: MethodLink) -> fmt::Result {
         match item.inner {
             clean::MethodItem(..) | clean::TyMethodItem(..) => {
                 try!(write!(w, "<h4 id='method.{}' class='{}'>{}<code>",
                             *item.name.as_ref().unwrap(),
                             shortty(item),
                             ConciseStability(&item.stability)));
-                try!(render_method(w, item));
+                try!(render_method(w, item, link));
                 try!(write!(w, "</code></h4>\n"));
             }
             clean::TypedefItem(ref tydef) => {
@@ -2247,10 +2273,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
 
     try!(write!(w, "<div class='impl-items'>"));
     for trait_item in i.impl_.items.iter() {
-        try!(doctraititem(w, trait_item, true));
+        try!(doctraititem(w, trait_item, true, link));
     }
 
     fn render_default_methods(w: &mut fmt::Formatter,
+                              did: ast::DefId,
                               t: &clean::Trait,
                               i: &clean::Impl) -> fmt::Result {
         for trait_item in &t.items {
@@ -2260,7 +2287,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
                 None => {}
             }
 
-            try!(doctraititem(w, trait_item, false));
+            try!(doctraititem(w, trait_item, false,
+                              MethodLink::GotoSource(did)));
         }
         Ok(())
     }
@@ -2271,7 +2299,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
     // for them work.
     if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ {
         if let Some(t) = cache().traits.get(&did) {
-            try!(render_default_methods(w, t, &i.impl_));
+            try!(render_default_methods(w, did, t, &i.impl_));
         }
     }
     try!(write!(w, "</div>"));