about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTom Jakubowski <tom@crystae.net>2014-11-20 11:22:09 -0800
committerTom Jakubowski <tom@crystae.net>2014-11-24 05:23:10 -0800
commitdd4c7c00d85a82d3ddda1b453ba2ce649a4d1b41 (patch)
treed3445ec9d973c70a6fc3f46aa202c340acc0e606
parentbad1062caaaefe0963d7b8513786c8283e74f1e7 (diff)
downloadrust-dd4c7c00d85a82d3ddda1b453ba2ce649a4d1b41.tar.gz
rust-dd4c7c00d85a82d3ddda1b453ba2ce649a4d1b41.zip
rustdoc: Render associated types on traits and impls
-rw-r--r--src/librustdoc/clean/mod.rs24
-rw-r--r--src/librustdoc/html/format.rs3
-rw-r--r--src/librustdoc/html/item_type.rs2
-rw-r--r--src/librustdoc/html/render.rs92
-rw-r--r--src/librustdoc/html/static/main.css13
-rw-r--r--src/librustdoc/lib.rs2
6 files changed, 96 insertions, 40 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f9c509cce14..3228c32a733 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -336,7 +336,7 @@ pub enum ItemEnum {
     ForeignStaticItem(Static),
     MacroItem(Macro),
     PrimitiveItem(PrimitiveType),
-    AssociatedTypeItem,
+    AssociatedTypeItem(TyParam),
 }
 
 #[deriving(Clone, Encodable, Decodable)]
@@ -982,6 +982,8 @@ impl Clean<Type> for ast::PolyTraitRef {
     }
 }
 
+/// An item belonging to a trait, whether a method or associated. Could be named
+/// TraitItem except that's already taken by an exported enum variant.
 #[deriving(Clone, Encodable, Decodable)]
 pub enum TraitMethod {
     RequiredMethod(Item),
@@ -1002,6 +1004,12 @@ impl TraitMethod {
             _ => false,
         }
     }
+    pub fn is_type(&self) -> bool {
+        match self {
+            &TypeTraitItem(..) => true,
+            _ => false,
+        }
+    }
     pub fn item<'a>(&'a self) -> &'a Item {
         match *self {
             RequiredMethod(ref item) => item,
@@ -2211,7 +2219,7 @@ impl Clean<Item> for ast::AssociatedType {
             source: self.ty_param.span.clean(cx),
             name: Some(self.ty_param.ident.clean(cx)),
             attrs: self.attrs.clean(cx),
-            inner: AssociatedTypeItem,
+            inner: AssociatedTypeItem(self.ty_param.clean(cx)),
             visibility: None,
             def_id: ast_util::local_def(self.ty_param.id),
             stability: None,
@@ -2225,7 +2233,17 @@ impl Clean<Item> for ty::AssociatedType {
             source: DUMMY_SP.clean(cx),
             name: Some(self.name.clean(cx)),
             attrs: Vec::new(),
-            inner: AssociatedTypeItem,
+            // FIXME(#18048): this is wrong, but cross-crate associated types are broken
+            // anyway, for the time being.
+            inner: AssociatedTypeItem(TyParam {
+                name: self.name.clean(cx),
+                did: ast::DefId {
+                    krate: 0,
+                    node: ast::DUMMY_NODE_ID
+                },
+                bounds: vec![],
+                default: None
+            }),
             visibility: None,
             def_id: self.def_id,
             stability: None,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 2b521d1da06..221caa64ef5 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -46,9 +46,8 @@ pub struct Stability<'a>(pub &'a Option<clean::Stability>);
 pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
 /// Wrapper struct for emitting a where clause from Generics.
 pub struct WhereClause<'a>(pub &'a clean::Generics);
-
 /// Wrapper struct for emitting type parameter bounds.
-struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
+pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
 
 impl VisSpace {
     pub fn get(&self) -> Option<ast::Visibility> {
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index daa5f155d51..cb3ad9d063f 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -95,7 +95,7 @@ pub fn shortty(item: &clean::Item) -> ItemType {
         clean::ForeignStaticItem(..)   => ForeignStatic,
         clean::MacroItem(..)           => Macro,
         clean::PrimitiveItem(..)       => Primitive,
-        clean::AssociatedTypeItem      => AssociatedType,
+        clean::AssociatedTypeItem(..)  => AssociatedType,
     }
 }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 466af36898e..24b5904b6d3 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -59,7 +59,7 @@ use clean;
 use doctree;
 use fold::DocFolder;
 use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
-use html::format::{ConciseStability, WhereClause};
+use html::format::{ConciseStability, TyParamBounds, WhereClause};
 use html::highlight;
 use html::item_type::{ItemType, shortty};
 use html::item_type;
@@ -1685,27 +1685,23 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                   t.generics,
                   bounds,
                   WhereClause(&t.generics)));
-    let required = t.items.iter()
-                          .filter(|m| {
-                              match **m {
-                                  clean::RequiredMethod(_) => true,
-                                  _ => false,
-                              }
-                          })
-                          .collect::<Vec<&clean::TraitMethod>>();
-    let provided = t.items.iter()
-                          .filter(|m| {
-                              match **m {
-                                  clean::ProvidedMethod(_) => true,
-                                  _ => false,
-                              }
-                          })
-                          .collect::<Vec<&clean::TraitMethod>>();
+
+    let types = t.items.iter().filter(|m| m.is_type()).collect::<Vec<_>>();
+    let required = t.items.iter().filter(|m| m.is_req()).collect::<Vec<_>>();
+    let provided = t.items.iter().filter(|m| m.is_def()).collect::<Vec<_>>();
 
     if t.items.len() == 0 {
         try!(write!(w, "{{ }}"));
     } else {
         try!(write!(w, "{{\n"));
+        for t in types.iter() {
+            try!(write!(w, "    "));
+            try!(render_method(w, t.item()));
+            try!(write!(w, ";\n"));
+        }
+        if types.len() > 0 && required.len() > 0 {
+            try!(w.write("\n".as_bytes()));
+        }
         for m in required.iter() {
             try!(write!(w, "    "));
             try!(render_method(w, m.item()));
@@ -1738,6 +1734,17 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         Ok(())
     }
 
+    if types.len() > 0 {
+        try!(write!(w, "
+            <h2 id='associated-types'>Associated Types</h2>
+            <div class='methods'>
+        "));
+        for t in types.iter() {
+            try!(trait_item(w, *t));
+        }
+        try!(write!(w, "</div>"));
+    }
+
     // Output the documentation for each function individually
     if required.len() > 0 {
         try!(write!(w, "
@@ -1792,7 +1799,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 }
 
 fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
-    fn fun(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
+    fn method(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
            g: &clean::Generics, selfty: &clean::SelfTy,
            d: &clean::FnDecl) -> fmt::Result {
         write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
@@ -1807,14 +1814,28 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
                decl = Method(selfty, d),
                where_clause = WhereClause(g))
     }
+    fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
+                  typ: &clean::TyParam) -> fmt::Result {
+        try!(write!(w, "type {}", it.name.as_ref().unwrap()));
+        if typ.bounds.len() > 0 {
+            try!(write!(w, ": {}", TyParamBounds(&*typ.bounds)))
+        }
+        if let Some(ref default) = typ.default {
+            try!(write!(w, " = {}", default));
+        }
+        Ok(())
+    }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
-            fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
         }
         clean::MethodItem(ref m) => {
-            fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
         }
-        _ => unreachable!()
+        clean::AssociatedTypeItem(ref typ) => {
+            assoc_type(w, meth, typ)
+        }
+        _ => panic!("render_method called on non-method")
     }
 }
 
@@ -2071,11 +2092,26 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
 
     fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
                     -> fmt::Result {
-        try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
-                    *item.name.as_ref().unwrap(),
-                    ConciseStability(&item.stability)));
-        try!(render_method(w, item));
-        try!(write!(w, "</code></h4>\n"));
+        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!(write!(w, "</code></h4>\n"));
+            }
+            clean::TypedefItem(ref tydef) => {
+                let name = item.name.as_ref().unwrap();
+                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>",
+                            *name,
+                            shortty(item),
+                            ConciseStability(&item.stability)));
+                try!(write!(w, "type {} = {}", name, tydef.type_));
+                try!(write!(w, "</code></h4>\n"));
+            }
+            _ => panic!("can't make docs for trait item with name {}", item.name)
+        }
         match item.doc_value() {
             Some(s) if dox => {
                 try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
@@ -2085,7 +2121,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
         }
     }
 
-    try!(write!(w, "<div class='impl-methods'>"));
+    try!(write!(w, "<div class='impl-items'>"));
     for trait_item in i.impl_.items.iter() {
         try!(doctraititem(w, trait_item, true));
     }
@@ -2107,6 +2143,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
 
     // If we've implemented a trait, then also emit documentation for all
     // default methods which weren't overridden in the implementation block.
+    // FIXME: this also needs to be done for associated types, whenever defaults
+    // for them work.
     match i.impl_.trait_ {
         Some(clean::ResolvedPath { did, .. }) => {
             try!({
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 4c019550395..dc62273364c 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -84,7 +84,7 @@ h2 {
 h3 {
     font-size: 1.3em;
 }
-h1, h2, h3:not(.impl):not(.method), h4:not(.method) {
+h1, h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
     color: black;
     font-weight: 500;
     margin: 20px 0 15px 0;
@@ -94,15 +94,15 @@ h1.fqn {
     border-bottom: 1px dashed #D5D5D5;
     margin-top: 0;
 }
-h2, h3:not(.impl):not(.method), h4:not(.method) {
+h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
     border-bottom: 1px solid #DDDDDD;
 }
-h3.impl, h3.method, h4.method {
+h3.impl, h3.method, h4.method, h3.type, h4.type {
     font-weight: 600;
     margin-top: 10px;
     margin-bottom: 10px;
 }
-h3.impl, h3.method {
+h3.impl, h3.method, h3.type {
     margin-top: 15px;
 }
 h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle {
@@ -235,6 +235,7 @@ nav.sub {
 .content .highlighted.fn { background-color: #c6afb3; }
 .content .highlighted.method { background-color: #c6afb3; }
 .content .highlighted.tymethod { background-color: #c6afb3; }
+.content .highlighted.type { background-color: #c6afb3; }
 .content .highlighted.ffi { background-color: #c6afb3; }
 
 .docblock.short.nowrap {
@@ -307,7 +308,7 @@ nav.sub {
 }
 .content .methods .docblock { margin-left: 40px; }
 
-.content .impl-methods .docblock { margin-left: 40px; }
+.content .impl-items .docblock { margin-left: 40px; }
 
 nav {
     border-bottom: 1px solid #e0e0e0;
@@ -442,7 +443,7 @@ h1 .stability {
     padding: 4px 10px;
 }
 
-.impl-methods .stability, .methods .stability {
+.impl-items .stability, .methods .stability {
     margin-right: 20px;
 }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 204f866e827..36e74d43e64 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -16,7 +16,7 @@
 #![crate_type = "rlib"]
 
 #![allow(unknown_features)]
-#![feature(globs, macro_rules, phase, slicing_syntax, tuple_indexing)]
+#![feature(globs, if_let, macro_rules, phase, slicing_syntax, tuple_indexing)]
 
 extern crate arena;
 extern crate getopts;