From 114537196f4ec5754eb895d2613f3a985820de42 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Mon, 28 Apr 2014 02:56:54 +0900 Subject: [PATCH 1/3] rustdoc: Add stability and source links to the methods. Fixes #12932. this change made most functions that render the methods to require the render `Context`, so they are now made into `Context` methods. --- src/librustdoc/html/markdown.rs | 4 +- src/librustdoc/html/render.rs | 1208 ++++++++++++++------------- src/librustdoc/html/static/main.css | 16 +- 3 files changed, 622 insertions(+), 606 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index fa285185a6184..f06b558e385cc 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -209,8 +209,8 @@ pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result { }; // Render the HTML - let text = format!(r#"{sec_len,plural,=0{}other{{sec} }}{}"#, + let text = format!("\ + {sec_len,plural,=0{}other{{sec} }}{}", s, lvl = level, id = id, sec_len = sec.len(), sec = sec); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b67d2683b303d..b55a7375c2b66 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -86,7 +86,7 @@ pub struct Context { /// header. This map will change depending on the surrounding context of the /// page. pub sidebar: HashMap<~str, Vec<~str> >, - /// This flag indicates whether [src] links should be generated or not. If + /// This flag indicates whether source links should be generated or not. If /// the source files are present in the html rendering, then this will be /// `true`. pub include_sources: bool, @@ -950,54 +950,19 @@ impl<'a> fmt::Show for Item<'a> { } try!(write!(fmt.buf, "{}", shortty(self.item), self.item.name.get_ref().as_slice())); - - // Write stability attributes - match attr::find_stability(self.item.attrs.iter()) { - Some(ref stability) => { - try!(write!(fmt.buf, - "{lvl}", - lvl = stability.level.to_str(), - reason = match stability.text { - Some(ref s) => (*s).clone(), - None => InternedString::new(""), - })); - } - None => {} - } - - // Write `src` tag - if self.cx.include_sources { - let mut path = Vec::new(); - clean_srcpath(self.item.source.filename.as_bytes(), |component| { - path.push(component.to_owned()); - }); - let href = if self.item.source.loline == self.item.source.hiline { - format!("{}", self.item.source.loline) - } else { - format!("{}-{}", self.item.source.loline, self.item.source.hiline) - }; - try!(write!(fmt.buf, - "\ - [src]", - root = self.cx.root_path, - krate = self.cx.layout.krate, - path = path.connect("/"), - href = href)); - } + try!(self.cx.item_heading_aux(fmt.buf, self.item)) try!(write!(fmt.buf, "\n")); match self.item.inner { - clean::ModuleItem(ref m) => { - item_module(fmt.buf, self.cx, self.item, m.items.as_slice()) - } + clean::ModuleItem(ref m) => + self.cx.item_module(fmt.buf, self.item, m.items.as_slice()), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt.buf, self.item, f), - clean::TraitItem(ref t) => item_trait(fmt.buf, self.item, t), - 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), + self.cx.item_function(fmt.buf, self.item, f), + clean::TraitItem(ref t) => self.cx.item_trait(fmt.buf, self.item, t), + clean::StructItem(ref s) => self.cx.item_struct(fmt.buf, self.item, s), + clean::EnumItem(ref e) => self.cx.item_enum(fmt.buf, self.item, e), + clean::TypedefItem(ref t) => self.cx.item_typedef(fmt.buf, self.item, t), + clean::MacroItem(ref m) => self.cx.item_macro(fmt.buf, self.item, m), _ => Ok(()) } } @@ -1044,633 +1009,657 @@ fn document(w: &mut Writer, item: &clean::Item) -> fmt::Result { Ok(()) } -fn item_module(w: &mut Writer, cx: &Context, - item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - try!(document(w, item)); - debug!("{:?}", items); - let mut indices = Vec::from_fn(items.len(), |i| i); +impl Context { + /// Renders auxiliary tags and links in the heading of given item. + /// Should be placed between the heading text and the closing tag. + fn item_heading_aux(&self, w: &mut Writer, item: &clean::Item) -> fmt::Result { + // Write stability attributes + match attr::find_stability(item.attrs.iter()) { + Some(ref stability) => { + try!(write!(w, + "{lvl} ", + lvl = stability.level.to_str(), + reason = match stability.text { + Some(ref s) => (*s).clone(), + None => InternedString::new(""), + })); + } + None => {} + } - fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering { - if shortty(i1) == shortty(i2) { - return i1.name.cmp(&i2.name); + // Write `src` tag + if self.include_sources { + let mut path = Vec::new(); + clean_srcpath(item.source.filename.as_bytes(), |component| { + path.push(component.to_owned()); + }); + let href = if item.source.loline == item.source.hiline { + format!("{}", item.source.loline) + } else { + format!("{}-{}", item.source.loline, item.source.hiline) + }; + try!(write!(w, + "\ + Source", + root = self.root_path, + krate = self.layout.krate, + path = path.connect("/"), + href = href)); } - match (&i1.inner, &i2.inner) { - (&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => { - match (&a.inner, &b.inner) { - (&clean::ExternCrate(..), _) => Less, - (_, &clean::ExternCrate(..)) => Greater, - _ => idx1.cmp(&idx2), + + Ok(()) + } + + fn item_module(&self, w: &mut Writer, + item: &clean::Item, items: &[clean::Item]) -> fmt::Result { + try!(document(w, item)); + debug!("{:?}", items); + let mut indices = Vec::from_fn(items.len(), |i| i); + + fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering { + if shortty(i1) == shortty(i2) { + return i1.name.cmp(&i2.name); + } + match (&i1.inner, &i2.inner) { + (&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => { + match (&a.inner, &b.inner) { + (&clean::ExternCrate(..), _) => Less, + (_, &clean::ExternCrate(..)) => Greater, + _ => idx1.cmp(&idx2), + } } + (&clean::ViewItemItem(..), _) => Less, + (_, &clean::ViewItemItem(..)) => Greater, + (&clean::ModuleItem(..), _) => Less, + (_, &clean::ModuleItem(..)) => Greater, + (&clean::MacroItem(..), _) => Less, + (_, &clean::MacroItem(..)) => Greater, + (&clean::StructItem(..), _) => Less, + (_, &clean::StructItem(..)) => Greater, + (&clean::EnumItem(..), _) => Less, + (_, &clean::EnumItem(..)) => Greater, + (&clean::StaticItem(..), _) => Less, + (_, &clean::StaticItem(..)) => Greater, + (&clean::ForeignFunctionItem(..), _) => Less, + (_, &clean::ForeignFunctionItem(..)) => Greater, + (&clean::ForeignStaticItem(..), _) => Less, + (_, &clean::ForeignStaticItem(..)) => Greater, + (&clean::TraitItem(..), _) => Less, + (_, &clean::TraitItem(..)) => Greater, + (&clean::FunctionItem(..), _) => Less, + (_, &clean::FunctionItem(..)) => Greater, + (&clean::TypedefItem(..), _) => Less, + (_, &clean::TypedefItem(..)) => Greater, + _ => idx1.cmp(&idx2), } - (&clean::ViewItemItem(..), _) => Less, - (_, &clean::ViewItemItem(..)) => Greater, - (&clean::ModuleItem(..), _) => Less, - (_, &clean::ModuleItem(..)) => Greater, - (&clean::MacroItem(..), _) => Less, - (_, &clean::MacroItem(..)) => Greater, - (&clean::StructItem(..), _) => Less, - (_, &clean::StructItem(..)) => Greater, - (&clean::EnumItem(..), _) => Less, - (_, &clean::EnumItem(..)) => Greater, - (&clean::StaticItem(..), _) => Less, - (_, &clean::StaticItem(..)) => Greater, - (&clean::ForeignFunctionItem(..), _) => Less, - (_, &clean::ForeignFunctionItem(..)) => Greater, - (&clean::ForeignStaticItem(..), _) => Less, - (_, &clean::ForeignStaticItem(..)) => Greater, - (&clean::TraitItem(..), _) => Less, - (_, &clean::TraitItem(..)) => Greater, - (&clean::FunctionItem(..), _) => Less, - (_, &clean::FunctionItem(..)) => Greater, - (&clean::TypedefItem(..), _) => Less, - (_, &clean::TypedefItem(..)) => Greater, - _ => idx1.cmp(&idx2), } - } - debug!("{:?}", indices); - indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); + debug!("{:?}", indices); + indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); - debug!("{:?}", indices); - let mut curty = None; - for &idx in indices.iter() { - let myitem = &items[idx]; + debug!("{:?}", indices); + let mut curty = None; + for &idx in indices.iter() { + let myitem = &items[idx]; - let myty = Some(shortty(myitem)); - if myty != curty { - if curty.is_some() { - try!(write!(w, "")); + let myty = Some(shortty(myitem)); + if myty != curty { + if curty.is_some() { + try!(write!(w, "")); + } + curty = myty; + let (short, name) = match myitem.inner { + clean::ModuleItem(..) => ("modules", "Modules"), + clean::StructItem(..) => ("structs", "Structs"), + clean::EnumItem(..) => ("enums", "Enums"), + clean::FunctionItem(..) => ("functions", "Functions"), + clean::TypedefItem(..) => ("types", "Type Definitions"), + clean::StaticItem(..) => ("statics", "Statics"), + clean::TraitItem(..) => ("traits", "Traits"), + clean::ImplItem(..) => ("impls", "Implementations"), + clean::ViewItemItem(..) => ("reexports", "Reexports"), + clean::TyMethodItem(..) => ("tymethods", "Type Methods"), + clean::MethodItem(..) => ("methods", "Methods"), + clean::StructFieldItem(..) => ("fields", "Struct Fields"), + clean::VariantItem(..) => ("variants", "Variants"), + clean::ForeignFunctionItem(..) => ("ffi-fns", "Foreign Functions"), + clean::ForeignStaticItem(..) => ("ffi-statics", "Foreign Statics"), + clean::MacroItem(..) => ("macros", "Macros"), + }; + try!(write!(w, + "

{name}

\n", + id = short, name = name)); } - curty = myty; - let (short, name) = match myitem.inner { - clean::ModuleItem(..) => ("modules", "Modules"), - clean::StructItem(..) => ("structs", "Structs"), - clean::EnumItem(..) => ("enums", "Enums"), - clean::FunctionItem(..) => ("functions", "Functions"), - clean::TypedefItem(..) => ("types", "Type Definitions"), - clean::StaticItem(..) => ("statics", "Statics"), - clean::TraitItem(..) => ("traits", "Traits"), - clean::ImplItem(..) => ("impls", "Implementations"), - clean::ViewItemItem(..) => ("reexports", "Reexports"), - clean::TyMethodItem(..) => ("tymethods", "Type Methods"), - clean::MethodItem(..) => ("methods", "Methods"), - clean::StructFieldItem(..) => ("fields", "Struct Fields"), - clean::VariantItem(..) => ("variants", "Variants"), - clean::ForeignFunctionItem(..) => ("ffi-fns", "Foreign Functions"), - clean::ForeignStaticItem(..) => ("ffi-statics", "Foreign Statics"), - clean::MacroItem(..) => ("macros", "Macros"), - }; - try!(write!(w, - "\n
", - id = short, name = name)); - } - match myitem.inner { - clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => { - struct Initializer<'a>(&'a str); - impl<'a> fmt::Show for Initializer<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Initializer(s) = *self; - if s.len() == 0 { return Ok(()); } - try!(write!(f.buf, " = ")); - let tag = if s.contains("\n") { "pre" } else { "code" }; - try!(write!(f.buf, "<{tag}>{}", - s.as_slice(), tag=tag)); - Ok(()) + match myitem.inner { + clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => { + struct Initializer<'a>(&'a str); + impl<'a> fmt::Show for Initializer<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Initializer(s) = *self; + if s.len() == 0 { return Ok(()); } + try!(write!(f.buf, " = ")); + let tag = if s.contains("\n") { "pre" } else { "code" }; + try!(write!(f.buf, "<{tag}>{}", + s.as_slice(), tag=tag)); + Ok(()) + } } + + try!(write!(w, " + + + + + ", + VisSpace(myitem.visibility), + *myitem.name.get_ref(), + s.type_, + Initializer(s.expr), + Markdown(blank(myitem.doc_value())))); } - try!(write!(w, " - - - - - ", - VisSpace(myitem.visibility), - *myitem.name.get_ref(), - s.type_, - Initializer(s.expr), - Markdown(blank(myitem.doc_value())))); - } + clean::ViewItemItem(ref item) => { + match item.inner { + clean::ExternCrate(ref name, ref src, _) => { + try!(write!(w, "")); + } - clean::ViewItemItem(ref item) => { - match item.inner { - clean::ExternCrate(ref name, ref src, _) => { - try!(write!(w, "", + VisSpace(myitem.visibility), + *import)); } - try!(write!(w, ";")); } - clean::Import(ref import) => { - try!(write!(w, "", - VisSpace(myitem.visibility), - *import)); - } } - } - - _ => { - if myitem.name.is_none() { continue } - try!(write!(w, " - - - - - ", - *myitem.name.get_ref(), - Markdown(shorter(myitem.doc_value())), - class = shortty(myitem), - href = item_path(myitem), - title = full_path(cx, myitem))); + _ => { + if myitem.name.is_none() { continue } + try!(write!(w, " + + + + + ", + *myitem.name.get_ref(), + Markdown(shorter(myitem.doc_value())), + class = shortty(myitem), + href = item_path(myitem), + title = full_path(self, myitem))); + } } } + write!(w, "
{}static {}: {}{}{} 
{}static {}: {}{}{} 
extern crate {}", + name.as_slice())); + match *src { + Some(ref src) => try!(write!(w, " = \"{}\"", + src.as_slice())), + None => {} + } + try!(write!(w, ";
extern crate {}", - name.as_slice())); - match *src { - Some(ref src) => try!(write!(w, " = \"{}\"", - src.as_slice())), - None => {} + clean::Import(ref import) => { + try!(write!(w, "
{}{}
{}{}
{}{}
{}{}
") } - write!(w, "") -} -fn item_function(w: &mut Writer, it: &clean::Item, - f: &clean::Function) -> fmt::Result { - try!(write!(w, "
{vis}{fn_style}fn \
-                    {name}{generics}{decl}
", - vis = VisSpace(it.visibility), - fn_style = FnStyleSpace(f.fn_style), - name = it.name.get_ref().as_slice(), - generics = f.generics, - decl = f.decl)); - document(w, it) -} - -fn item_trait(w: &mut Writer, it: &clean::Item, - t: &clean::Trait) -> fmt::Result { - let mut parents = StrBuf::new(); - if t.parents.len() > 0 { - parents.push_str(": "); - for (i, p) in t.parents.iter().enumerate() { - if i > 0 { parents.push_str(" + "); } - parents.push_str(format!("{}", *p)); - } + fn item_function(&self, w: &mut Writer, it: &clean::Item, + f: &clean::Function) -> fmt::Result { + try!(write!(w, "
{vis}{fn_style}fn \
+                        {name}{generics}{decl}
", + vis = VisSpace(it.visibility), + fn_style = FnStyleSpace(f.fn_style), + name = it.name.get_ref().as_slice(), + generics = f.generics, + decl = f.decl)); + document(w, it) } - // Output the trait definition - try!(write!(w, "
{}trait {}{}{} ",
-                  VisSpace(it.visibility),
-                  it.name.get_ref().as_slice(),
-                  t.generics,
-                  parents));
-    let required = t.methods.iter().filter(|m| m.is_req()).collect::>();
-    let provided = t.methods.iter().filter(|m| !m.is_req()).collect::>();
-
-    if t.methods.len() == 0 {
-        try!(write!(w, "\\{ \\}"));
-    } else {
-        try!(write!(w, "\\{\n"));
-        for m in required.iter() {
-            try!(write!(w, "    "));
-            try!(render_method(w, m.item()));
-            try!(write!(w, ";\n"));
+    fn item_trait(&self, w: &mut Writer, it: &clean::Item,
+                  t: &clean::Trait) -> fmt::Result {
+        let mut parents = StrBuf::new();
+        if t.parents.len() > 0 {
+            parents.push_str(": ");
+            for (i, p) in t.parents.iter().enumerate() {
+                if i > 0 { parents.push_str(" + "); }
+                parents.push_str(format!("{}", *p));
+            }
         }
-        if required.len() > 0 && provided.len() > 0 {
-            try!(w.write("\n".as_bytes()));
+
+        // Output the trait definition
+        try!(write!(w, "
{}trait {}{}{} ",
+                      VisSpace(it.visibility),
+                      it.name.get_ref().as_slice(),
+                      t.generics,
+                      parents));
+        let required: Vec<&clean::TraitMethod> =
+            t.methods.iter().filter(|m| m.is_req()).collect();
+        let provided: Vec<&clean::TraitMethod> =
+            t.methods.iter().filter(|m| !m.is_req()).collect();
+
+        if t.methods.len() == 0 {
+            try!(write!(w, "\\{ \\}"));
+        } else {
+            try!(write!(w, "\\{\n"));
+            for m in required.iter() {
+                try!(write!(w, "    "));
+                try!(self.render_method(w, m.item()));
+                try!(write!(w, ";\n"));
+            }
+            if required.len() > 0 && provided.len() > 0 {
+                try!(w.write("\n".as_bytes()));
+            }
+            for m in provided.iter() {
+                try!(write!(w, "    "));
+                try!(self.render_method(w, m.item()));
+                try!(write!(w, " \\{ ... \\}\n"));
+            }
+            try!(write!(w, "\\}"));
         }
-        for m in provided.iter() {
-            try!(write!(w, "    "));
-            try!(render_method(w, m.item()));
-            try!(write!(w, " \\{ ... \\}\n"));
+        try!(write!(w, "
")); + + // Trait documentation + try!(document(w, it)); + + fn meth(w: &mut Writer, cx: &Context, m: &clean::TraitMethod) -> fmt::Result { + try!(write!(w, "

", + shortty(m.item()), + *m.item().name.get_ref())); + try!(cx.render_method(w, m.item())); + try!(write!(w, "")); + try!(cx.item_heading_aux(w, m.item())); + try!(write!(w, "

")); + try!(document(w, m.item())); + Ok(()) } - try!(write!(w, "\\}")); - } - try!(write!(w, "
")); - - // Trait documentation - try!(document(w, it)); - - fn meth(w: &mut Writer, m: &clean::TraitMethod) -> fmt::Result { - try!(write!(w, "

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

")); - try!(document(w, m.item())); - Ok(()) - } - // Output the documentation for each function individually - if required.len() > 0 { - try!(write!(w, " -

Required Methods

-
- ")); - for m in required.iter() { - try!(meth(w, *m)); + // Output the documentation for each function individually + if required.len() > 0 { + try!(write!(w, " +

Required Methods

+
+ ")); + for m in required.iter() { + try!(meth(w, self, *m)); + } + try!(write!(w, "
")); } - try!(write!(w, "
")); - } - if provided.len() > 0 { - try!(write!(w, " -

Provided Methods

-
- ")); - for m in provided.iter() { - try!(meth(w, *m)); + if provided.len() > 0 { + try!(write!(w, " +

Provided Methods

+
+ ")); + for m in provided.iter() { + try!(meth(w, self, *m)); + } + try!(write!(w, "
")); } - try!(write!(w, "
")); - } - local_data::get(cache_key, |cache| { - let cache = cache.unwrap(); - match cache.implementors.find(&it.id) { - Some(implementors) => { - try!(write!(w, " -

Implementors

- ")); + None => {} } - None => {} - } - Ok(()) - }) -} - -fn render_method(w: &mut Writer, meth: &clean::Item) -> fmt::Result { - fn fun(w: &mut Writer, it: &clean::Item, fn_style: ast::FnStyle, - g: &clean::Generics, selfty: &clean::SelfTy, - d: &clean::FnDecl) -> fmt::Result { - write!(w, "{}fn {name}\ - {generics}{decl}", - match fn_style { - ast::UnsafeFn => "unsafe ", - _ => "", - }, - ty = shortty(it), - name = it.name.get_ref().as_slice(), - generics = *g, - decl = Method(selfty, d)) + Ok(()) + }) } - match meth.inner { - clean::TyMethodItem(ref m) => { - fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl) + + fn render_method(&self, w: &mut Writer, meth: &clean::Item) -> fmt::Result { + fn fun(w: &mut Writer, it: &clean::Item, fn_style: ast::FnStyle, + g: &clean::Generics, selfty: &clean::SelfTy, + d: &clean::FnDecl) -> fmt::Result { + write!(w, "{}fn {name}\ + {generics}{decl}", + match fn_style { + ast::UnsafeFn => "unsafe ", + _ => "", + }, + ty = shortty(it), + name = it.name.get_ref().as_slice(), + generics = *g, + decl = Method(selfty, d)) } - clean::MethodItem(ref m) => { - fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl) + match meth.inner { + clean::TyMethodItem(ref m) => { + fun(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) + } + _ => unreachable!() } - _ => unreachable!() } -} -fn item_struct(w: &mut Writer, it: &clean::Item, - s: &clean::Struct) -> fmt::Result { - try!(write!(w, "
"));
-    try!(render_struct(w,
-                       it,
-                       Some(&s.generics),
-                       s.struct_type,
-                       s.fields.as_slice(),
-                       "",
-                       true));
-    try!(write!(w, "
")); - - try!(document(w, it)); - let mut fields = s.fields.iter().filter(|f| { - match f.inner { - clean::StructFieldItem(clean::HiddenStructField) => false, - clean::StructFieldItem(clean::TypedStructField(..)) => true, - _ => false, - } - }).peekable(); - match s.struct_type { - doctree::Plain if fields.peek().is_some() => { - try!(write!(w, "

Fields

\n")); - for field in fields { - try!(write!(w, "")); + fn item_struct(&self, w: &mut Writer, it: &clean::Item, + s: &clean::Struct) -> fmt::Result { + try!(write!(w, "
"));
+        try!(self.render_struct(w,
+                                it,
+                                Some(&s.generics),
+                                s.struct_type,
+                                s.fields.as_slice(),
+                                "",
+                                true));
+        try!(write!(w, "
")); + + try!(document(w, it)); + let mut fields = s.fields.iter().filter(|f| { + match f.inner { + clean::StructFieldItem(clean::HiddenStructField) => false, + clean::StructFieldItem(clean::TypedStructField(..)) => true, + _ => false, } - try!(write!(w, "
\ - {name}", - name = field.name.get_ref().as_slice())); - try!(document(w, field)); - try!(write!(w, "
")); + }).peekable(); + match s.struct_type { + doctree::Plain if fields.peek().is_some() => { + try!(write!(w, "

Fields

\n")); + for field in fields { + try!(write!(w, "")); + } + try!(write!(w, "
\ + {name}", + name = field.name.get_ref().as_slice())); + try!(document(w, field)); + try!(write!(w, "
")); + } + _ => {} } - _ => {} + self.render_methods(w, it) } - render_methods(w, it) -} -fn item_enum(w: &mut Writer, it: &clean::Item, e: &clean::Enum) -> fmt::Result { - try!(write!(w, "
{}enum {}{}",
-                  VisSpace(it.visibility),
-                  it.name.get_ref().as_slice(),
-                  e.generics));
-    if e.variants.len() == 0 && !e.variants_stripped {
-        try!(write!(w, " \\{\\}"));
-    } else {
-        try!(write!(w, " \\{\n"));
-        for v in e.variants.iter() {
-            try!(write!(w, "    "));
-            let name = v.name.get_ref().as_slice();
-            match v.inner {
-                clean::VariantItem(ref var) => {
-                    match var.kind {
-                        clean::CLikeVariant => try!(write!(w, "{}", name)),
-                        clean::TupleVariant(ref tys) => {
-                            try!(write!(w, "{}(", name));
-                            for (i, ty) in tys.iter().enumerate() {
-                                if i > 0 {
-                                    try!(write!(w, ", "))
+    fn item_enum(&self, w: &mut Writer, it: &clean::Item, e: &clean::Enum) -> fmt::Result {
+        try!(write!(w, "
{}enum {}{}",
+                      VisSpace(it.visibility),
+                      it.name.get_ref().as_slice(),
+                      e.generics));
+        if e.variants.len() == 0 && !e.variants_stripped {
+            try!(write!(w, " \\{\\}"));
+        } else {
+            try!(write!(w, " \\{\n"));
+            for v in e.variants.iter() {
+                try!(write!(w, "    "));
+                let name = v.name.get_ref().as_slice();
+                match v.inner {
+                    clean::VariantItem(ref var) => {
+                        match var.kind {
+                            clean::CLikeVariant => try!(write!(w, "{}", name)),
+                            clean::TupleVariant(ref tys) => {
+                                try!(write!(w, "{}(", name));
+                                for (i, ty) in tys.iter().enumerate() {
+                                    if i > 0 {
+                                        try!(write!(w, ", "))
+                                    }
+                                    try!(write!(w, "{}", *ty));
                                 }
-                                try!(write!(w, "{}", *ty));
+                                try!(write!(w, ")"));
+                            }
+                            clean::StructVariant(ref s) => {
+                                try!(self.render_struct(w,
+                                                        v,
+                                                        None,
+                                                        s.struct_type,
+                                                        s.fields.as_slice(),
+                                                        "    ",
+                                                        false));
                             }
-                            try!(write!(w, ")"));
-                        }
-                        clean::StructVariant(ref s) => {
-                            try!(render_struct(w,
-                                               v,
-                                               None,
-                                               s.struct_type,
-                                               s.fields.as_slice(),
-                                               "    ",
-                                               false));
                         }
                     }
+                    _ => unreachable!()
                 }
-                _ => unreachable!()
+                try!(write!(w, ",\n"));
             }
-            try!(write!(w, ",\n"));
-        }
 
-        if e.variants_stripped {
-            try!(write!(w, "    // some variants omitted\n"));
+            if e.variants_stripped {
+                try!(write!(w, "    // some variants omitted\n"));
+            }
+            try!(write!(w, "\\}"));
         }
-        try!(write!(w, "\\}"));
-    }
-    try!(write!(w, "
")); - - try!(document(w, it)); - if e.variants.len() > 0 { - try!(write!(w, "

Variants

\n")); - for variant in e.variants.iter() { - try!(write!(w, "")); } - try!(write!(w, "")); - } - try!(write!(w, "
{name}", - name = variant.name.get_ref().as_slice())); - try!(document(w, variant)); - match variant.inner { - clean::VariantItem(ref var) => { - match var.kind { - clean::StructVariant(ref s) => { - let mut fields = s.fields.iter().filter(|f| { - match f.inner { - clean::StructFieldItem(ref t) => match *t { - clean::HiddenStructField => false, - clean::TypedStructField(..) => true, - }, - _ => false, + try!(write!(w, "")); + + try!(document(w, it)); + if e.variants.len() > 0 { + try!(write!(w, "

Variants

\n")); + for variant in e.variants.iter() { + try!(write!(w, "
{name}", + name = variant.name.get_ref().as_slice())); + try!(document(w, variant)); + match variant.inner { + clean::VariantItem(ref var) => { + match var.kind { + clean::StructVariant(ref s) => { + let mut fields = s.fields.iter().filter(|f| { + match f.inner { + clean::StructFieldItem(ref t) => match *t { + clean::HiddenStructField => false, + clean::TypedStructField(..) => true, + }, + _ => false, + } + }); + try!(write!(w, "

Fields

\n + ")); + for field in fields { + try!(write!(w, "")); } - }); - try!(write!(w, "

Fields

\n -
\ + {f}", + v = variant.name.get_ref().as_slice(), + f = field.name.get_ref().as_slice())); + try!(document(w, field)); + try!(write!(w, "
")); - for field in fields { - try!(write!(w, "")); + try!(write!(w, "
\ - {f}", - v = variant.name.get_ref().as_slice(), - f = field.name.get_ref().as_slice())); - try!(document(w, field)); - try!(write!(w, "
")); } - try!(write!(w, "
")); + _ => () } - _ => () } + _ => () } - _ => () + try!(write!(w, "
")); - - } - try!(render_methods(w, it)); - Ok(()) -} + try!(write!(w, "")); -fn render_struct(w: &mut Writer, it: &clean::Item, - g: Option<&clean::Generics>, - ty: doctree::StructType, - fields: &[clean::Item], - tab: &str, - structhead: bool) -> fmt::Result { - try!(write!(w, "{}{}{}", - VisSpace(it.visibility), - if structhead {"struct "} else {""}, - it.name.get_ref().as_slice())); - match g { - Some(g) => try!(write!(w, "{}", *g)), - None => {} + } + try!(self.render_methods(w, it)); + Ok(()) } - match ty { - doctree::Plain => { - try!(write!(w, " \\{\n{}", tab)); - let mut fields_stripped = false; - for field in fields.iter() { - match field.inner { - clean::StructFieldItem(clean::HiddenStructField) => { - fields_stripped = true; - } - clean::StructFieldItem(clean::TypedStructField(ref ty)) => { - try!(write!(w, " {}{}: {},\n{}", - VisSpace(field.visibility), - field.name.get_ref().as_slice(), - *ty, - tab)); - } - _ => unreachable!(), - }; - } - if fields_stripped { - try!(write!(w, " // some fields omitted\n{}", tab)); - } - try!(write!(w, "\\}")); + fn render_struct(&self, w: &mut Writer, it: &clean::Item, + g: Option<&clean::Generics>, + ty: doctree::StructType, + fields: &[clean::Item], + tab: &str, + structhead: bool) -> fmt::Result { + try!(write!(w, "{}{}{}", + VisSpace(it.visibility), + if structhead {"struct "} else {""}, + it.name.get_ref().as_slice())); + match g { + Some(g) => try!(write!(w, "{}", *g)), + None => {} } - doctree::Tuple | doctree::Newtype => { - try!(write!(w, "(")); - for (i, field) in fields.iter().enumerate() { - if i > 0 { - try!(write!(w, ", ")); + match ty { + doctree::Plain => { + try!(write!(w, " \\{\n{}", tab)); + let mut fields_stripped = false; + for field in fields.iter() { + match field.inner { + clean::StructFieldItem(clean::HiddenStructField) => { + fields_stripped = true; + } + clean::StructFieldItem(clean::TypedStructField(ref ty)) => { + try!(write!(w, " {}{}: {},\n{}", + VisSpace(field.visibility), + field.name.get_ref().as_slice(), + *ty, + tab)); + } + _ => unreachable!(), + }; } - match field.inner { - clean::StructFieldItem(clean::HiddenStructField) => { - try!(write!(w, "_")) - } - clean::StructFieldItem(clean::TypedStructField(ref ty)) => { - try!(write!(w, "{}{}", VisSpace(field.visibility), *ty)) - } - _ => unreachable!() + + if fields_stripped { + try!(write!(w, " // some fields omitted\n{}", tab)); } + try!(write!(w, "\\}")); } - try!(write!(w, ");")); - } - doctree::Unit => { - try!(write!(w, ";")); - } - } - Ok(()) -} - -fn render_methods(w: &mut Writer, it: &clean::Item) -> fmt::Result { - local_data::get(cache_key, |cache| { - let c = cache.unwrap(); - match c.impls.find(&it.id) { - Some(v) => { - let mut non_trait = v.iter().filter(|p| { - p.ref0().trait_.is_none() - }); - let non_trait = non_trait.collect::)>>(); - let mut traits = v.iter().filter(|p| { - p.ref0().trait_.is_some() - }); - let traits = traits.collect::)>>(); - - if non_trait.len() > 0 { - try!(write!(w, "

Methods

")); - for &(ref i, ref dox) in non_trait.move_iter() { - try!(render_impl(w, i, dox)); + doctree::Tuple | doctree::Newtype => { + try!(write!(w, "(")); + for (i, field) in fields.iter().enumerate() { + if i > 0 { + try!(write!(w, ", ")); } - } - if traits.len() > 0 { - try!(write!(w, "

Trait \ - Implementations

")); - let mut any_derived = false; - for & &(ref i, ref dox) in traits.iter() { - if !i.derived { - try!(render_impl(w, i, dox)); - } else { - any_derived = true; + match field.inner { + clean::StructFieldItem(clean::HiddenStructField) => { + try!(write!(w, "_")) } - } - if any_derived { - try!(write!(w, "

Derived Implementations \ -

")); - for &(ref i, ref dox) in traits.move_iter() { - if i.derived { - try!(render_impl(w, i, dox)); - } + clean::StructFieldItem(clean::TypedStructField(ref ty)) => { + try!(write!(w, "{}{}", VisSpace(field.visibility), *ty)) } + _ => unreachable!() } } + try!(write!(w, ");")); } - None => {} - } - Ok(()) - }) -} - -fn render_impl(w: &mut Writer, i: &clean::Impl, - dox: &Option<~str>) -> fmt::Result { - try!(write!(w, "

impl{} ", i.generics)); - let trait_id = match i.trait_ { - Some(ref ty) => { - try!(write!(w, "{} for ", *ty)); - match *ty { - clean::ResolvedPath { id, .. } => Some(id), - _ => None, - } - } - None => None - }; - try!(write!(w, "{}

", i.for_)); - match *dox { - Some(ref dox) => { - try!(write!(w, "
{}
", - Markdown(dox.as_slice()))); - } - None => {} - } - - fn docmeth(w: &mut Writer, item: &clean::Item) -> io::IoResult { - try!(write!(w, "

", - *item.name.get_ref())); - try!(render_method(w, item)); - try!(write!(w, "

\n")); - match item.doc_value() { - Some(s) => { - try!(write!(w, "
{}
", Markdown(s))); - Ok(true) + doctree::Unit => { + try!(write!(w, ";")); } - None => Ok(false) } + Ok(()) } - try!(write!(w, "
")); - for meth in i.methods.iter() { - if try!(docmeth(w, meth)) { - continue - } + fn render_methods(&self, w: &mut Writer, it: &clean::Item) -> fmt::Result { + local_data::get(cache_key, |cache| { + let c = cache.unwrap(); + match c.impls.find(&it.id) { + Some(v) => { + let mut non_trait = v.iter().filter(|p| { + p.ref0().trait_.is_none() + }); + let non_trait = non_trait.collect::)>>(); + let mut traits = v.iter().filter(|p| { + p.ref0().trait_.is_some() + }); + let traits = traits.collect::)>>(); - // No documentation? Attempt to slurp in the trait's documentation - let trait_id = match trait_id { - None => continue, - Some(id) => id, - }; - try!(local_data::get(cache_key, |cache| { - let cache = cache.unwrap(); - match cache.traits.find(&trait_id) { - Some(t) => { - let name = meth.name.clone(); - match t.methods.iter().find(|t| t.item().name == name) { - Some(method) => { - match method.item().doc_value() { - Some(s) => { - try!(write!(w, - "
{}
", - Markdown(s))); + if non_trait.len() > 0 { + try!(write!(w, "

Methods

")); + for &(ref i, ref dox) in non_trait.move_iter() { + try!(self.render_impl(w, i, dox)); + } + } + if traits.len() > 0 { + try!(write!(w, "

Trait \ + Implementations

")); + let mut any_derived = false; + for & &(ref i, ref dox) in traits.iter() { + if !i.derived { + try!(self.render_impl(w, i, dox)); + } else { + any_derived = true; + } + } + if any_derived { + try!(write!(w, "

Derived \ + Implementations

")); + for &(ref i, ref dox) in traits.move_iter() { + if i.derived { + try!(self.render_impl(w, i, dox)); } - None => {} } } - None => {} } } None => {} } Ok(()) - })) + }) } - // If we've implemented a trait, then also emit documentation for all - // default methods which weren't overridden in the implementation block. - match trait_id { - None => {} - Some(id) => { + fn render_impl(&self, w: &mut Writer, i: &clean::Impl, + dox: &Option<~str>) -> fmt::Result { + try!(write!(w, "

impl{} ", i.generics)); + let trait_id = match i.trait_ { + Some(ref ty) => { + try!(write!(w, "{} for ", *ty)); + match *ty { + clean::ResolvedPath { id, .. } => Some(id), + _ => None, + } + } + None => None + }; + try!(write!(w, "{}

", i.for_)); + match *dox { + Some(ref dox) => { + try!(write!(w, "
{}
", + Markdown(dox.as_slice()))); + } + None => {} + } + + fn docmeth(w: &mut Writer, cx: &Context, + item: &clean::Item) -> io::IoResult { + try!(write!(w, "

", + *item.name.get_ref())); + try!(cx.render_method(w, item)); + try!(write!(w, "")); + try!(cx.item_heading_aux(w, item)); + try!(write!(w, "

\n")); + match item.doc_value() { + Some(s) => { + try!(write!(w, "
{}
", Markdown(s))); + Ok(true) + } + None => Ok(false) + } + } + + try!(write!(w, "
")); + for meth in i.methods.iter() { + if try!(docmeth(w, self, meth)) { + continue + } + + // No documentation? Attempt to slurp in the trait's documentation + let trait_id = match trait_id { + None => continue, + Some(id) => id, + }; try!(local_data::get(cache_key, |cache| { let cache = cache.unwrap(); - match cache.traits.find(&id) { + match cache.traits.find(&trait_id) { Some(t) => { - for method in t.methods.iter() { - let n = method.item().name.clone(); - match i.methods.iter().find(|m| m.name == n) { - Some(..) => continue, - None => {} + let name = meth.name.clone(); + match t.methods.iter().find(|t| t.item().name == name) { + Some(method) => { + match method.item().doc_value() { + Some(s) => { + try!(write!(w, + "
{}
", + Markdown(s))); + } + None => {} + } } - - try!(docmeth(w, method.item())); + None => {} } } None => {} @@ -1678,19 +1667,51 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, Ok(()) })) } + + // If we've implemented a trait, then also emit documentation for all + // default methods which weren't overridden in the implementation block. + match trait_id { + None => {} + Some(id) => { + try!(local_data::get(cache_key, |cache| { + let cache = cache.unwrap(); + match cache.traits.find(&id) { + Some(t) => { + for method in t.methods.iter() { + let n = method.item().name.clone(); + match i.methods.iter().find(|m| m.name == n) { + Some(..) => continue, + None => {} + } + + try!(docmeth(w, self, method.item())); + } + } + None => {} + } + Ok(()) + })) + } + } + try!(write!(w, "
")); + Ok(()) } - try!(write!(w, "
")); - Ok(()) -} -fn item_typedef(w: &mut Writer, it: &clean::Item, - t: &clean::Typedef) -> fmt::Result { - try!(write!(w, "
type {}{} = {};
", - it.name.get_ref().as_slice(), - t.generics, - t.type_)); + fn item_typedef(&self, w: &mut Writer, it: &clean::Item, + t: &clean::Typedef) -> fmt::Result { + try!(write!(w, "
type {}{} = {};
", + it.name.get_ref().as_slice(), + t.generics, + t.type_)); - document(w, it) + document(w, it) + } + + fn item_macro(&self, w: &mut Writer, it: &clean::Item, + t: &clean::Macro) -> fmt::Result { + try!(w.write_str(highlight::highlight(t.source, Some("macro")))); + document(w, it) + } } impl<'a> fmt::Show for Sidebar<'a> { @@ -1786,8 +1807,3 @@ impl<'a> fmt::Show for Source<'a> { } } -fn item_macro(w: &mut Writer, it: &clean::Item, - t: &clean::Macro) -> fmt::Result { - try!(w.write_str(highlight::highlight(t.source, Some("macro")))); - document(w, it) -} diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index b5ce3919bdd79..63587e90f741b 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -81,7 +81,7 @@ h3.impl, h4.method { h3.impl { margin-top: 15px; } -h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table a { +h1, h2, h3, h4, section.sidebar, .source-link, .search-input, .content table a { font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } @@ -217,7 +217,7 @@ nav.sub { .docblock h2 { font-size: 1.15em; } .docblock h3, .docblock h4, .docblock h5 { font-size: 1em; } -.content .source { +.content .source-link { float: right; font-size: 23px; } @@ -388,12 +388,12 @@ pre.rust .doccomment { color: #4D4D4C; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .lifetime { color: #B76514; } -h1.section-link:hover a:after, -h2.section-link:hover a:after, -h3.section-link:hover a:after, -h4.section-link:hover a:after, -h5.section-link:hover a:after, -h6.section-link:hover a:after { +h1:hover a.section-link:after, +h2:hover a.section-link:after, +h3:hover a.section-link:after, +h4:hover a.section-link:after, +h5:hover a.section-link:after, +h6:hover a.section-link:after { content: '\2002\00a7\2002'; } From bad1dab99e1c27bf87021fc74b0a7c142239e9ad Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Mon, 28 Apr 2014 03:03:03 +0900 Subject: [PATCH 2/3] syntax: Correct span for provided trait methods. --- src/libsyntax/parse/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 88110a87e6cf8..857b690ae2216 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1075,9 +1075,9 @@ impl<'a> Parser<'a> { p.parse_arg_general(false) }); - let hi = p.last_span.hi; match p.token { token::SEMI => { + let hi = p.last_span.hi; p.bump(); debug!("parse_trait_methods(): parsing required method"); // NB: at the moment, visibility annotations on required @@ -1100,6 +1100,7 @@ impl<'a> Parser<'a> { debug!("parse_trait_methods(): parsing provided method"); let (inner_attrs, body) = p.parse_inner_attrs_and_block(); + let hi = p.last_span.hi; let attrs = attrs.append(inner_attrs.as_slice()); Provided(@ast::Method { ident: ident, From 64d617809279adca6f9f31255d68194f775446b8 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Mon, 28 Apr 2014 03:03:35 +0900 Subject: [PATCH 3/3] rustdoc: A quick CSS tweak for stability and source links. this makes a source link much more visible (and link-like), and makes a stability index more consistent for the top-level headings and the method signature. this should be better than nothing, but further adjustments and/or redesigns are welcomed. --- src/librustdoc/html/static/main.css | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 63587e90f741b..9d0a2285ceb08 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -219,7 +219,11 @@ nav.sub { .content .source-link { float: right; - font-size: 23px; + font-size: 90%; + font-weight: 400; + border-radius: 3px; + padding: 2px 10px; + background-color: #ddd; } .content table { @@ -361,9 +365,11 @@ a { } .stability { - border-left: 6px solid #000; - border-radius: 3px; - padding: 2px 10px; + font-size: 90%; + font-weight: 400; + font-style: italic; + border-bottom: 2px solid #000; + padding: 2px 5px; text-transform: lowercase; margin-left: 10px; }