about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-27 04:51:13 -0700
committerbors <bors@rust-lang.org>2013-09-27 04:51:13 -0700
commit74dfd93bad2a2343f330cbea38c702192095210a (patch)
tree6e23e4c16c926979443daf47b9bf245da2dd9a51 /src
parentae8a2ff37976b069b24bd0558c7af3474dab5854 (diff)
parent42bcf638b0213747e01af87353413755b9ebc270 (diff)
downloadrust-74dfd93bad2a2343f330cbea38c702192095210a.tar.gz
rust-74dfd93bad2a2343f330cbea38c702192095210a.zip
auto merge of #9540 : alexcrichton/rust/more-rustdoc-improvements, r=brson
Commit messages have the details, mostly just knocking out more low-hanging-fruit type issues.
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean.rs58
-rw-r--r--src/librustdoc/doctree.rs2
-rw-r--r--src/librustdoc/html/render.rs108
-rw-r--r--src/librustdoc/html/static/main.css15
-rw-r--r--src/librustdoc/passes.rs53
-rw-r--r--src/librustdoc/visit_ast.rs3
-rw-r--r--src/libsyntax/attr.rs2
-rw-r--r--src/libsyntax/parse/parser.rs6
8 files changed, 204 insertions, 43 deletions
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index ae7cbf76bcc..623ac82486d 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -16,6 +16,7 @@ use its = syntax::parse::token::ident_to_str;
 use syntax;
 use syntax::ast;
 use syntax::ast_util;
+use syntax::attr;
 use syntax::attr::AttributeMethods;
 
 use std;
@@ -149,6 +150,8 @@ pub enum ItemEnum {
     MethodItem(Method),
     StructFieldItem(StructField),
     VariantItem(Variant),
+    ForeignFunctionItem(Function),
+    ForeignStaticItem(Static),
 }
 
 #[deriving(Clone, Encodable, Decodable)]
@@ -172,6 +175,7 @@ impl Clean<Item> for doctree::Module {
             inner: ModuleItem(Module {
                items: std::vec::concat(&[self.structs.clean(),
                               self.enums.clean(), self.fns.clean(),
+                              std::vec::concat(self.foreigns.clean()),
                               self.mods.clean(), self.typedefs.clean(),
                               self.statics.clean(), self.traits.clean(),
                               self.impls.clean(), self.view_items.clean()])
@@ -203,6 +207,25 @@ impl Clean<Attribute> for ast::Attribute {
     }
 }
 
+// This is a rough approximation that gets us what we want.
+impl<'self> attr::AttrMetaMethods for &'self Attribute {
+    fn name(&self) -> @str {
+        match **self {
+            Word(ref n) | List(ref n, _) | NameValue(ref n, _) =>
+                n.to_managed()
+        }
+    }
+
+    fn value_str(&self) -> Option<@str> {
+        match **self {
+            NameValue(_, ref v) => Some(v.to_managed()),
+            _ => None,
+        }
+    }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
+    fn name_str_pair(&self) -> Option<(@str, @str)> { None }
+}
+
 #[deriving(Clone, Encodable, Decodable)]
 pub struct TyParam {
     name: ~str,
@@ -968,6 +991,41 @@ impl Clean<ViewListIdent> for ast::path_list_ident {
     }
 }
 
+impl Clean<~[Item]> for ast::foreign_mod {
+    fn clean(&self) -> ~[Item] {
+        self.items.clean()
+    }
+}
+
+impl Clean<Item> for ast::foreign_item {
+    fn clean(&self) -> Item {
+        let inner = match self.node {
+            ast::foreign_item_fn(ref decl, ref generics) => {
+                ForeignFunctionItem(Function {
+                    decl: decl.clean(),
+                    generics: generics.clean(),
+                    purity: ast::extern_fn,
+                })
+            }
+            ast::foreign_item_static(ref ty, mutbl) => {
+                ForeignStaticItem(Static {
+                    type_: ty.clean(),
+                    mutability: if mutbl {Mutable} else {Immutable},
+                    expr: ~"",
+                })
+            }
+        };
+        Item {
+            name: Some(self.ident.clean()),
+            attrs: self.attrs.clean(),
+            source: self.span.clean(),
+            id: self.id,
+            visibility: self.vis.clean(),
+            inner: inner,
+        }
+    }
+}
+
 // Utilities
 
 trait ToSource {
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index a4e3f795498..835781907f3 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -30,6 +30,7 @@ pub struct Module {
     traits: ~[Trait],
     vis: ast::visibility,
     impls: ~[Impl],
+    foreigns: ~[ast::foreign_mod],
     view_items: ~[ast::view_item],
 }
 
@@ -50,6 +51,7 @@ impl Module {
             traits     : ~[],
             impls      : ~[],
             view_items : ~[],
+            foreigns   : ~[],
         }
     }
 }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 4f8c11d8285..3320842c046 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -28,6 +28,7 @@ use extra::json::ToJson;
 use extra::sort;
 
 use syntax::ast;
+use syntax::attr;
 
 use clean;
 use doctree;
@@ -521,6 +522,14 @@ impl Context {
                             }
                         }
                     }
+                    clean::StructItem(s) => {
+                        let mut it = s.fields.move_iter();
+                        do self.recurse(name) |this| {
+                            for item in it {
+                                f(this, item);
+                            }
+                        }
+                    }
                     _ => {}
                 }
             }
@@ -532,19 +541,21 @@ impl Context {
 
 fn shortty(item: &clean::Item) -> &'static str {
     match item.inner {
-        clean::ModuleItem(*)      => "mod",
-        clean::StructItem(*)      => "struct",
-        clean::EnumItem(*)        => "enum",
-        clean::FunctionItem(*)    => "fn",
-        clean::TypedefItem(*)     => "typedef",
-        clean::StaticItem(*)      => "static",
-        clean::TraitItem(*)       => "trait",
-        clean::ImplItem(*)        => "impl",
-        clean::ViewItemItem(*)    => "viewitem",
-        clean::TyMethodItem(*)    => "tymethod",
-        clean::MethodItem(*)      => "method",
-        clean::StructFieldItem(*) => "structfield",
-        clean::VariantItem(*)     => "variant",
+        clean::ModuleItem(*)          => "mod",
+        clean::StructItem(*)          => "struct",
+        clean::EnumItem(*)            => "enum",
+        clean::FunctionItem(*)        => "fn",
+        clean::TypedefItem(*)         => "typedef",
+        clean::StaticItem(*)          => "static",
+        clean::TraitItem(*)           => "trait",
+        clean::ImplItem(*)            => "impl",
+        clean::ViewItemItem(*)        => "viewitem",
+        clean::TyMethodItem(*)        => "tymethod",
+        clean::MethodItem(*)          => "method",
+        clean::StructFieldItem(*)     => "structfield",
+        clean::VariantItem(*)         => "variant",
+        clean::ForeignFunctionItem(*) => "ffi",
+        clean::ForeignStaticItem(*)   => "ffs",
     }
 }
 
@@ -558,6 +569,18 @@ impl<'self> Item<'self> {
 
 impl<'self> fmt::Default for Item<'self> {
     fn fmt(it: &Item<'self>, fmt: &mut fmt::Formatter) {
+        match attr::find_stability(it.item.attrs.iter()) {
+            Some(stability) => {
+                write!(fmt.buf,
+                       "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
+                       lvl = stability.level.to_str(),
+                       reason = match stability.text {
+                           Some(s) => s, None => @"",
+                       });
+            }
+            None => {}
+        }
+
         // Write the breadcrumb trail header for the top
         write!(fmt.buf, "<h1 class='fqn'>");
         match it.item.inner {
@@ -584,12 +607,15 @@ impl<'self> fmt::Default for Item<'self> {
         match it.item.inner {
             clean::ModuleItem(ref m) => item_module(fmt.buf, it.cx,
                                                     it.item, m.items),
-            clean::FunctionItem(ref f) => item_function(fmt.buf, it.item, f),
+            clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) =>
+                item_function(fmt.buf, it.item, f),
             clean::TraitItem(ref t) => item_trait(fmt.buf, it.item, t),
             clean::StructItem(ref s) => item_struct(fmt.buf, it.item, s),
             clean::EnumItem(ref e) => item_enum(fmt.buf, it.item, e),
             clean::TypedefItem(ref t) => item_typedef(fmt.buf, it.item, t),
             clean::VariantItem(*) => item_variant(fmt.buf, it.cx, it.item),
+            clean::StructFieldItem(*) => item_struct_field(fmt.buf, it.cx,
+                                                           it.item),
             _ => {}
         }
     }
@@ -663,6 +689,10 @@ fn item_module(w: &mut io::Writer, cx: &Context,
             (_, &clean::EnumItem(*)) => false,
             (&clean::StaticItem(*), _) => true,
             (_, &clean::StaticItem(*)) => false,
+            (&clean::ForeignFunctionItem(*), _) => true,
+            (_, &clean::ForeignFunctionItem(*)) => false,
+            (&clean::ForeignStaticItem(*), _) => true,
+            (_, &clean::ForeignStaticItem(*)) => false,
             (&clean::TraitItem(*), _) => true,
             (_, &clean::TraitItem(*)) => false,
             (&clean::FunctionItem(*), _) => true,
@@ -690,27 +720,31 @@ fn item_module(w: &mut io::Writer, cx: &Context,
             }
             curty = myty;
             write!(w, "<h2>{}</h2>\n<table>", match myitem.inner {
-                clean::ModuleItem(*)      => "Modules",
-                clean::StructItem(*)      => "Structs",
-                clean::EnumItem(*)        => "Enums",
-                clean::FunctionItem(*)    => "Functions",
-                clean::TypedefItem(*)     => "Type Definitions",
-                clean::StaticItem(*)      => "Statics",
-                clean::TraitItem(*)       => "Traits",
-                clean::ImplItem(*)        => "Implementations",
-                clean::ViewItemItem(*)    => "Reexports",
-                clean::TyMethodItem(*)    => "Type Methods",
-                clean::MethodItem(*)      => "Methods",
-                clean::StructFieldItem(*) => "Struct Fields",
-                clean::VariantItem(*)     => "Variants",
+                clean::ModuleItem(*)          => "Modules",
+                clean::StructItem(*)          => "Structs",
+                clean::EnumItem(*)            => "Enums",
+                clean::FunctionItem(*)        => "Functions",
+                clean::TypedefItem(*)         => "Type Definitions",
+                clean::StaticItem(*)          => "Statics",
+                clean::TraitItem(*)           => "Traits",
+                clean::ImplItem(*)            => "Implementations",
+                clean::ViewItemItem(*)        => "Reexports",
+                clean::TyMethodItem(*)        => "Type Methods",
+                clean::MethodItem(*)          => "Methods",
+                clean::StructFieldItem(*)     => "Struct Fields",
+                clean::VariantItem(*)         => "Variants",
+                clean::ForeignFunctionItem(*) => "Foreign Functions",
+                clean::ForeignStaticItem(*)   => "Foreign Statics",
             });
         }
 
         match myitem.inner {
-            clean::StaticItem(ref s) => {
+            clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => {
                 struct Initializer<'self>(&'self str);
                 impl<'self> fmt::Default for Initializer<'self> {
                     fn fmt(s: &Initializer<'self>, f: &mut fmt::Formatter) {
+                        if s.len() == 0 { return; }
+                        write!(f.buf, "<code> = </code>");
                         let tag = if s.contains("\n") { "pre" } else { "code" };
                         write!(f.buf, "<{tag}>{}</{tag}>",
                                s.as_slice(), tag=tag);
@@ -719,7 +753,7 @@ fn item_module(w: &mut io::Writer, cx: &Context,
 
                 write!(w, "
                     <tr>
-                        <td><code>{}static {}: {} = </code>{}</td>
+                        <td><code>{}static {}: {}</code>{}</td>
                         <td class='docblock'>{}&nbsp;</td>
                     </tr>
                 ",
@@ -980,11 +1014,12 @@ fn render_struct(w: &mut io::Writer, it: &clean::Item,
             for field in fields.iter() {
                 match field.inner {
                     clean::StructFieldItem(ref ty) => {
-                        write!(w, "    {}{}: {},\n{}",
+                        write!(w, "    {}<a name='field.{name}'>{name}</a>: \
+                                   {},\n{}",
                                VisSpace(field.visibility),
-                               field.name.get_ref().as_slice(),
                                ty.type_,
-                               tab);
+                               tab,
+                               name = field.name.get_ref().as_slice());
                     }
                     _ => unreachable!()
                 }
@@ -1170,3 +1205,12 @@ fn item_variant(w: &mut io::Writer, cx: &Context, it: &clean::Item) {
            *cx.current.last(),
            it.name.get_ref().as_slice());
 }
+
+fn item_struct_field(w: &mut io::Writer, cx: &Context, it: &clean::Item) {
+    write!(w, "<DOCTYPE html><html><head>\
+                <meta http-equiv='refresh' content='0; \
+                      url=../struct.{}.html\\#field.{}'>\
+               </head><body></body></html>",
+           *cx.current.last(),
+           it.name.get_ref().as_slice());
+}
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 97f59798240..11ca7a09311 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -269,3 +269,18 @@ a {
     float: left;
     padding: 20px;
 }
+
+.stability {
+    border-left: 5px solid #000;
+    border-radius: 3px;
+    padding: 0 3px;
+    float: right;
+    background: #fff;
+    text-transform: lowercase;
+}
+.stability.Deprecated { border-color: #D60027; color: #880017; }
+.stability.Experimental { border-color: #EC5315; color: #a53c0e; }
+.stability.Unstable { border-color: #FFD700; color: #b39800; }
+.stability.Stable { border-color: #AEC516; color: #7c8b10; }
+.stability.Frozen { border-color: #009431; color: #007726; }
+.stability.Locked { border-color: #0084B6; color: #00668c; }
diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs
index 91e2b3bfcf1..bf35c93caae 100644
--- a/src/librustdoc/passes.rs
+++ b/src/librustdoc/passes.rs
@@ -10,6 +10,7 @@
 
 use std::num;
 use std::uint;
+use std::hashmap::HashSet;
 
 use syntax::ast;
 
@@ -50,16 +51,18 @@ pub fn strip_hidden(crate: clean::Crate) -> plugins::PluginResult {
 
 /// Strip private items from the point of view of a crate or externally from a
 /// crate, specified by the `xcrate` flag.
-pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
-    struct Stripper;
-    impl fold::DocFolder for Stripper {
+pub fn strip_private(mut crate: clean::Crate) -> plugins::PluginResult {
+    // This stripper collects all *retained* nodes.
+    struct Stripper<'self>(&'self mut HashSet<ast::NodeId>);
+    impl<'self> fold::DocFolder for Stripper<'self> {
         fn fold_item(&mut self, i: Item) -> Option<Item> {
             match i.inner {
                 // These items can all get re-exported
                 clean::TypedefItem(*) | clean::StaticItem(*) |
                 clean::StructItem(*) | clean::EnumItem(*) |
                 clean::TraitItem(*) | clean::FunctionItem(*) |
-                clean::ViewItemItem(*) | clean::MethodItem(*) => {
+                clean::ViewItemItem(*) | clean::MethodItem(*) |
+                clean::ForeignFunctionItem(*) | clean::ForeignStaticItem(*) => {
                     // XXX: re-exported items should get surfaced in the docs as
                     //      well (using the output of resolve analysis)
                     if i.visibility != Some(ast::public) {
@@ -97,6 +100,7 @@ pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
             };
 
             let i = if fastreturn {
+                self.insert(i.id);
                 return Some(i);
             } else {
                 self.fold_item_recur(i)
@@ -108,15 +112,50 @@ pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
                         // emptied modules/impls have no need to exist
                         clean::ModuleItem(ref m) if m.items.len() == 0 => None,
                         clean::ImplItem(ref i) if i.methods.len() == 0 => None,
-                        _ => Some(i),
+                        _ => {
+                            self.insert(i.id);
+                            Some(i)
+                        }
                     }
                 }
                 None => None,
             }
         }
     }
-    let mut stripper = Stripper;
-    let crate = stripper.fold_crate(crate);
+
+    // This stripper discards all private impls of traits
+    struct ImplStripper<'self>(&'self HashSet<ast::NodeId>);
+    impl<'self> fold::DocFolder for ImplStripper<'self> {
+        fn fold_item(&mut self, i: Item) -> Option<Item> {
+            match i.inner {
+                clean::ImplItem(ref imp) => {
+                    match imp.trait_ {
+                        Some(clean::ResolvedPath{ id, _ }) => {
+                            if !self.contains(&id) {
+                                return None;
+                            }
+                        }
+                        Some(*) | None => {}
+                    }
+                }
+                _ => {}
+            }
+            self.fold_item_recur(i)
+        }
+    }
+
+    let mut retained = HashSet::new();
+    // First, strip all private items
+    {
+        let mut stripper = Stripper(&mut retained);
+        crate = stripper.fold_crate(crate);
+    }
+
+    // Next, strip all private implementations of traits
+    {
+        let mut stripper = ImplStripper(&retained);
+        crate = stripper.fold_crate(crate);
+    }
     (crate, None)
 }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index c4b9b9efe56..8e89c07ef00 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -174,6 +174,9 @@ impl RustdocVisitor {
                     };
                     om.impls.push(i);
                 },
+                ast::item_foreign_mod(ref fm) => {
+                    om.foreigns.push(fm.clone());
+                }
                 _ => (),
             }
         }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 295485d6f6e..47a7d0fbf9e 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -320,7 +320,7 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[deriving(Eq,Ord,Clone)]
+#[deriving(Eq,Ord,Clone,ToStr)]
 pub enum StabilityLevel {
     Deprecated,
     Experimental,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cc5143977cf..6c905c252c1 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4219,9 +4219,9 @@ impl Parser {
     }
 
     // parse a function declaration from a foreign module
-    fn parse_item_foreign_fn(&self,  attrs: ~[Attribute]) -> @foreign_item {
+    fn parse_item_foreign_fn(&self, vis: ast::visibility,
+                             attrs: ~[Attribute]) -> @foreign_item {
         let lo = self.span.lo;
-        let vis = self.parse_visibility();
 
         // Parse obsolete purity.
         let purity = self.parse_fn_purity();
@@ -4755,7 +4755,7 @@ impl Parser {
         if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) ||
                 self.is_keyword(keywords::Unsafe)) {
             // FOREIGN FUNCTION ITEM
-            let item = self.parse_item_foreign_fn(attrs);
+            let item = self.parse_item_foreign_fn(visibility, attrs);
             return iovi_foreign_item(item);
         }
         self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)