about summary refs log tree commit diff
path: root/src/librustdoc/html
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2014-07-04 00:51:46 -0700
committerAaron Turon <aturon@mozilla.com>2014-07-10 20:51:35 -0700
commit4d16de01d0beb84dc4a351022ea5cb587b4ab557 (patch)
treef51d913f9828ac455dee055e58f2f9846f8c8868 /src/librustdoc/html
parentb57d272e9908e164a72bd1a688141031705e1208 (diff)
downloadrust-4d16de01d0beb84dc4a351022ea5cb587b4ab557.tar.gz
rust-4d16de01d0beb84dc4a351022ea5cb587b4ab557.zip
rustdoc: Add stability dashboard
This commit adds a crate-level dashboard summarizing the stability
levels of all items for all submodules of the crate.

The information is also written as a json file, intended for consumption
by pages like http://huonw.github.io/isrustfastyet/

Closes #13541
Diffstat (limited to 'src/librustdoc/html')
-rw-r--r--src/librustdoc/html/format.rs70
-rw-r--r--src/librustdoc/html/render.rs56
-rw-r--r--src/librustdoc/html/static/main.css11
3 files changed, 131 insertions, 6 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 382e299d28d..84c0f0b97a1 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -22,6 +22,7 @@ use syntax::ast;
 use syntax::ast_util;
 
 use clean;
+use stability_summary::ModuleSummary;
 use html::item_type;
 use html::item_type::ItemType;
 use html::render;
@@ -631,3 +632,72 @@ impl<'a> fmt::Show for ConciseStability<'a> {
         }
     }
 }
+
+impl fmt::Show for ModuleSummary {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt_inner<'a>(f: &mut fmt::Formatter,
+                         context: &mut Vec<&'a str>,
+                         m: &'a ModuleSummary)
+                     -> fmt::Result {
+            let cnt = m.counts;
+            let tot = cnt.total();
+            if tot == 0 { return Ok(()) }
+
+            context.push(m.name.as_slice());
+            let path = context.connect("::");
+
+            // the total width of each row's stability summary, in pixels
+            let width = 500;
+
+            try!(write!(f, "<tr>"));
+            try!(write!(f, "<td class='summary'>\
+                            <a class='summary' href='{}'>{}</a></td>",
+                        Vec::from_slice(context.slice_from(1))
+                            .append_one("index.html").connect("/"),
+                        path));
+            try!(write!(f, "<td>"));
+            try!(write!(f, "<span class='summary Stable' \
+                            style='width: {}px; display: inline-block'>&nbsp</span>",
+                        (width * cnt.stable)/tot));
+            try!(write!(f, "<span class='summary Unstable' \
+                            style='width: {}px; display: inline-block'>&nbsp</span>",
+                        (width * cnt.unstable)/tot));
+            try!(write!(f, "<span class='summary Experimental' \
+                            style='width: {}px; display: inline-block'>&nbsp</span>",
+                        (width * cnt.experimental)/tot));
+            try!(write!(f, "<span class='summary Deprecated' \
+                            style='width: {}px; display: inline-block'>&nbsp</span>",
+                        (width * cnt.deprecated)/tot));
+            try!(write!(f, "<span class='summary Unmarked' \
+                            style='width: {}px; display: inline-block'>&nbsp</span>",
+                        (width * cnt.unmarked)/tot));
+            try!(write!(f, "</td></tr>"));
+
+            for submodule in m.submodules.iter() {
+                try!(fmt_inner(f, context, submodule));
+            }
+            context.pop();
+            Ok(())
+        }
+
+        let mut context = Vec::new();
+
+        try!(write!(f,
+r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{}</a></h1>
+This dashboard summarizes the stability levels for all of the public modules of
+the crate, according to the total number of items at each level in the module and its children:
+<blockquote>
+<a class='stability Stable'></a> stable,<br/>
+<a class='stability Unstable'></a> unstable,<br/>
+<a class='stability Experimental'></a> experimental,<br/>
+<a class='stability Deprecated'></a> deprecated,<br/>
+<a class='stability Unmarked'></a> unmarked
+</blockquote>
+The counts do not include methods or trait
+implementations that are visible only through a re-exported type.",
+self.name));
+        try!(write!(f, "<table>"))
+        try!(fmt_inner(f, &mut context, self));
+        write!(f, "</table>")
+    }
+}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 70edbcf86e1..3761f918332 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -43,6 +43,8 @@ use std::sync::Arc;
 
 use externalfiles::ExternalHtml;
 
+use serialize::json;
+use serialize::Encodable;
 use serialize::json::ToJson;
 use syntax::ast;
 use syntax::ast_util;
@@ -59,6 +61,7 @@ use html::item_type;
 use html::layout;
 use html::markdown::Markdown;
 use html::markdown;
+use stability_summary;
 
 /// Major driving force in all rustdoc rendering. This contains information
 /// about where in the tree-like hierarchy rendering is occurring and controls
@@ -249,6 +252,11 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
 
     try!(mkdir(&cx.dst));
 
+    // Crawl the crate, building a summary of the stability levels.  NOTE: this
+    // summary *must* be computed with the original `krate`; the folding below
+    // removes the impls from their modules.
+    let summary = stability_summary::build(&krate);
+
     // Crawl the crate attributes looking for attributes which control how we're
     // going to emit HTML
     match krate.module.as_ref().map(|m| m.doc_list().unwrap_or(&[])) {
@@ -361,7 +369,7 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
     let krate = try!(render_sources(&mut cx, krate));
 
     // And finally render the whole crate's documentation
-    cx.krate(krate)
+    cx.krate(krate, summary)
 }
 
 fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::IoResult<String> {
@@ -1045,13 +1053,34 @@ impl Context {
     ///
     /// This currently isn't parallelized, but it'd be pretty easy to add
     /// parallelization to this function.
-    fn krate(self, mut krate: clean::Crate) -> io::IoResult<()> {
+    fn krate(mut self, mut krate: clean::Crate,
+             stability: stability_summary::ModuleSummary) -> io::IoResult<()> {
         let mut item = match krate.module.take() {
             Some(i) => i,
             None => return Ok(())
         };
         item.name = Some(krate.name);
 
+        // render stability dashboard
+        try!(self.recurse(stability.name.clone(), |this| {
+            let json_dst = &this.dst.join("stability.json");
+            let mut json_out = BufferedWriter::new(try!(File::create(json_dst)));
+            try!(stability.encode(&mut json::Encoder::new(&mut json_out)));
+
+            let title = stability.name.clone().append(" - Stability dashboard");
+            let page = layout::Page {
+                ty: "mod",
+                root_path: this.root_path.as_slice(),
+                title: title.as_slice(),
+            };
+            let html_dst = &this.dst.join("stability.html");
+            let mut html_out = BufferedWriter::new(try!(File::create(html_dst)));
+            layout::render(&mut html_out, &this.layout, &page,
+                           &Sidebar{ cx: this, item: &item },
+                           &stability)
+        }));
+
+        // render the crate documentation
         let mut work = vec!((self, item));
         loop {
             match work.pop() {
@@ -1061,6 +1090,7 @@ impl Context {
                 None => break,
             }
         }
+
         Ok(())
     }
 
@@ -1233,6 +1263,8 @@ impl<'a> Item<'a> {
     }
 }
 
+
+
 impl<'a> fmt::Show for Item<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         // Write the breadcrumb trail header for the top
@@ -1269,6 +1301,17 @@ impl<'a> fmt::Show for Item<'a> {
         // Write stability level
         try!(write!(fmt, "{}", Stability(&self.item.stability)));
 
+        // Links to out-of-band information, i.e. src and stability dashboard
+        try!(write!(fmt, "<span class='out-of-band'>"));
+
+        // Write stability dashboard link
+        match self.item.inner {
+            clean::ModuleItem(ref m) if m.is_crate => {
+                try!(write!(fmt, "<a href='stability.html'>[stability dashboard]</a> "));
+            }
+            _ => {}
+        };
+
         // Write `src` tag
         //
         // When this item is part of a `pub use` in a downstream crate, the
@@ -1278,14 +1321,15 @@ impl<'a> fmt::Show for Item<'a> {
         if self.cx.include_sources && !is_primitive {
             match self.href() {
                 Some(l) => {
-                    try!(write!(fmt,
-                                "<a class='source' id='src-{}' \
-                                    href='{}'>[src]</a>",
+                    try!(write!(fmt, "<a id='src-{}' href='{}'>[src]</a>",
                                 self.item.def_id.node, l));
                 }
                 None => {}
             }
         }
+
+        try!(write!(fmt, "</span>"));
+
         try!(write!(fmt, "</h1>\n"));
 
         match self.item.inner {
@@ -1355,6 +1399,7 @@ fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
 fn item_module(w: &mut fmt::Formatter, cx: &Context,
                item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
     try!(document(w, item));
+
     let mut indices = range(0, items.len()).filter(|i| {
         !ignore_private_item(&items[*i])
     }).collect::<Vec<uint>>();
@@ -1514,6 +1559,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
             }
         }
     }
+
     write!(w, "</table>")
 }
 
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index f65198fcfe2..4f790f96750 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -238,7 +238,7 @@ nav.sub {
 .docblock h2 { font-size: 1.15em; }
 .docblock h3, .docblock h4, .docblock h5 { font-size: 1em; }
 
-.content .source {
+.content .out-of-band {
     float: right;
     font-size: 23px;
 }
@@ -409,6 +409,15 @@ h1 .stability {
 .stability.Locked { border-color: #0084B6; color: #00668c; }
 .stability.Unmarked { border-color: #FFFFFF; }
 
+.summary {
+    padding-right: 0px;
+}
+.summary.Deprecated { background-color: #A071A8; }
+.summary.Experimental { background-color: #D46D6A; }
+.summary.Unstable { background-color: #D4B16A; }
+.summary.Stable { background-color: #54A759; }
+.summary.Unmarked { background-color: #FFFFFF; }
+
 :target { background: #FDFFD3; }
 
 /* Code highlighting */