about summary refs log tree commit diff
path: root/src/librustdoc/markdown_pass.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/markdown_pass.rs')
-rw-r--r--src/librustdoc/markdown_pass.rs918
1 files changed, 457 insertions, 461 deletions
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
index 8c4cd26bb7c..2dfc04e8ec7 100644
--- a/src/librustdoc/markdown_pass.rs
+++ b/src/librustdoc/markdown_pass.rs
@@ -22,10 +22,6 @@ use markdown_writer::WriterFactory;
 use pass::Pass;
 use sort_pass;
 
-#[cfg(test)] use config;
-#[cfg(test)] use markdown_writer;
-#[cfg(test)] use page_pass;
-
 use core::cell::Cell;
 use core::str;
 use core::vec;
@@ -48,8 +44,8 @@ fn run(
     fn mods_last(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool {
         fn is_mod(item: &doc::ItemTag) -> bool {
             match *item {
-              doc::ModTag(_) => true,
-              _ => false
+                doc::ModTag(_) => true,
+                _ => false
             }
         }
 
@@ -69,33 +65,6 @@ fn run(
     return doc;
 }
 
-#[test]
-fn should_write_modules_last() {
-    /*
-    Because the markdown pass writes all modules at the same level of
-    indentation (it doesn't 'nest' them), we need to make sure that we
-    write all of the modules contained in each module after all other
-    types of items, or else the header nesting will end up wrong, with
-    modules appearing to contain items that they do not.
-    */
-    let markdown = test::render(
-        ~"mod a { }\
-         fn b() { }\
-         mod c {
-         }\
-         fn d() { }"
-    );
-
-    let idx_a = str::find_str(markdown, ~"# Module `a`").get();
-    let idx_b = str::find_str(markdown, ~"## Function `b`").get();
-    let idx_c = str::find_str(markdown, ~"# Module `c`").get();
-    let idx_d = str::find_str(markdown, ~"## Function `d`").get();
-
-    assert!(idx_b < idx_d);
-    assert!(idx_d < idx_a);
-    assert!(idx_a < idx_c);
-}
-
 struct Ctxt {
     w: Writer
 }
@@ -118,33 +87,18 @@ pub fn write_markdown(
 fn write_page(ctxt: &Ctxt, page: &doc::Page) {
     write_title(ctxt, copy *page);
     match copy *page {
-      doc::CratePage(doc) => {
-        write_crate(ctxt, doc);
-      }
-      doc::ItemPage(doc) => {
-        // We don't write a header for item's pages because their
-        // header in the html output is created by the page title
-        write_item_no_header(ctxt, doc);
-      }
+        doc::CratePage(doc) => {
+            write_crate(ctxt, doc);
+        }
+        doc::ItemPage(doc) => {
+            // We don't write a header for item's pages because their
+            // header in the html output is created by the page title
+            write_item_no_header(ctxt, doc);
+        }
     }
     ctxt.w.put_done();
 }
 
-#[test]
-fn should_request_new_writer_for_each_page() {
-    // This port will send us a (page, str) pair for every writer
-    // that was created
-    let (writer_factory, po) = markdown_writer::future_writer_factory();
-    let (srv, doc) = test::create_doc_srv(~"mod a { }");
-    // Split the document up into pages
-    let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
-    write_markdown(doc, writer_factory);
-    // We expect two pages to have been written
-    for iter::repeat(2) {
-        po.recv();
-    }
-}
-
 fn write_title(ctxt: &Ctxt, page: doc::Page) {
     ctxt.w.put_line(fmt!("%% %s", make_title(page)));
     ctxt.w.put_line(~"");
@@ -152,38 +106,18 @@ fn write_title(ctxt: &Ctxt, page: doc::Page) {
 
 fn make_title(page: doc::Page) -> ~str {
     let item = match page {
-      doc::CratePage(CrateDoc) => {
-        doc::ModTag(copy CrateDoc.topmod)
-      }
-      doc::ItemPage(ItemTag) => {
-        ItemTag
-      }
+        doc::CratePage(CrateDoc) => {
+            doc::ModTag(copy CrateDoc.topmod)
+        }
+        doc::ItemPage(ItemTag) => {
+            ItemTag
+        }
     };
     let title = markdown_pass::header_text(item);
     let title = str::replace(title, ~"`", ~"");
     return title;
 }
 
-#[test]
-fn should_write_title_for_each_page() {
-    let (writer_factory, po) = markdown_writer::future_writer_factory();
-    let (srv, doc) = test::create_doc_srv(
-        ~"#[link(name = \"core\")]; mod a { }");
-    let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
-    write_markdown(doc, writer_factory);
-    for iter::repeat(2) {
-        let (page, markdown) = po.recv();
-        match page {
-          doc::CratePage(_) => {
-            assert!(str::contains(markdown, ~"% Crate core"));
-          }
-          doc::ItemPage(_) => {
-            assert!(str::contains(markdown, ~"% Module a"));
-          }
-        }
-    }
-}
-
 enum Hlvl {
     H1 = 1,
     H2 = 2,
@@ -204,94 +138,94 @@ fn write_header_(ctxt: &Ctxt, lvl: Hlvl, title: ~str) {
 
 pub fn header_kind(doc: doc::ItemTag) -> ~str {
     match doc {
-      doc::ModTag(_) => {
-        if doc.id() == syntax::ast::crate_node_id {
-            ~"Crate"
-        } else {
-            ~"Module"
+        doc::ModTag(_) => {
+            if doc.id() == syntax::ast::crate_node_id {
+                ~"Crate"
+            } else {
+                ~"Module"
+            }
+        }
+        doc::NmodTag(_) => {
+            ~"Foreign module"
+        }
+        doc::FnTag(_) => {
+            ~"Function"
+        }
+        doc::ConstTag(_) => {
+            ~"Const"
+        }
+        doc::EnumTag(_) => {
+            ~"Enum"
+        }
+        doc::TraitTag(_) => {
+            ~"Trait"
+        }
+        doc::ImplTag(_) => {
+            ~"Implementation"
+        }
+        doc::TyTag(_) => {
+            ~"Type"
+        }
+        doc::StructTag(_) => {
+            ~"Struct"
         }
-      }
-      doc::NmodTag(_) => {
-        ~"Foreign module"
-      }
-      doc::FnTag(_) => {
-        ~"Function"
-      }
-      doc::ConstTag(_) => {
-        ~"Const"
-      }
-      doc::EnumTag(_) => {
-        ~"Enum"
-      }
-      doc::TraitTag(_) => {
-        ~"Trait"
-      }
-      doc::ImplTag(_) => {
-        ~"Implementation"
-      }
-      doc::TyTag(_) => {
-        ~"Type"
-      }
-      doc::StructTag(_) => {
-        ~"Struct"
-      }
     }
 }
 
 pub fn header_name(doc: doc::ItemTag) -> ~str {
     let fullpath = str::connect(doc.path() + ~[doc.name()], ~"::");
     match &doc {
-      &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => {
-        fullpath
-      }
-      &doc::NmodTag(_) => {
-        fullpath
-      }
-      &doc::ImplTag(ref doc) => {
-        assert!(doc.self_ty.is_some());
-          let bounds = if (&doc.bounds_str).is_some() {
-              fmt!(" where %s", (&doc.bounds_str).get())
-          } else {
-              ~""
-          };
-        let self_ty = (&doc.self_ty).get();
-        let mut trait_part = ~"";
-        for doc.trait_types.eachi |i, trait_type| {
-            if i == 0 {
-                trait_part += ~" of ";
+        &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => {
+            fullpath
+        }
+        &doc::NmodTag(_) => {
+            fullpath
+        }
+        &doc::ImplTag(ref doc) => {
+            assert!(doc.self_ty.is_some());
+            let bounds = if (&doc.bounds_str).is_some() {
+                fmt!(" where %s", (&doc.bounds_str).get())
             } else {
-                trait_part += ~", ";
+                ~""
+            };
+            let self_ty = (&doc.self_ty).get();
+            let mut trait_part = ~"";
+            for doc.trait_types.eachi |i, trait_type| {
+                if i == 0 {
+                    trait_part += ~" of ";
+                } else {
+                    trait_part += ~", ";
+                }
+                trait_part += *trait_type;
             }
-            trait_part += *trait_type;
+            fmt!("%s for %s%s", trait_part, self_ty, bounds)
+        }
+        _ => {
+            doc.name()
         }
-        fmt!("%s for %s%s", trait_part, self_ty, bounds)
-      }
-      _ => {
-        doc.name()
-      }
     }
 }
 
 pub fn header_text(doc: doc::ItemTag) -> ~str {
     match &doc {
-      &doc::ImplTag(ref ImplDoc) => {
-        let header_kind = header_kind(copy doc);
-          let bounds = if (&ImplDoc.bounds_str).is_some() {
-              fmt!(" where `%s`", (&ImplDoc.bounds_str).get())
-          } else {
-              ~""
-          };
-        let desc = if ImplDoc.trait_types.is_empty() {
-            fmt!("for `%s`%s", (&ImplDoc.self_ty).get(), bounds)
-        } else {
-            fmt!("of `%s` for `%s`%s",
-                 ImplDoc.trait_types[0],
-                 (&ImplDoc.self_ty).get(),
-                 bounds)
-        };
-        return fmt!("%s %s", header_kind, desc);
-      }
-      _ => {}
+        &doc::ImplTag(ref ImplDoc) => {
+            let header_kind = header_kind(copy doc);
+            let bounds = if (&ImplDoc.bounds_str).is_some() {
+                fmt!(" where `%s`", (&ImplDoc.bounds_str).get())
+            } else {
+                ~""
+            };
+            let desc = if ImplDoc.trait_types.is_empty() {
+                fmt!("for `%s`%s", (&ImplDoc.self_ty).get(), bounds)
+            } else {
+                fmt!("of `%s` for `%s`%s",
+                     ImplDoc.trait_types[0],
+                     (&ImplDoc.self_ty).get(),
+                     bounds)
+            };
+            return fmt!("%s %s", header_kind, desc);
+        }
+        _ => {}
     }
 
     header_text_(header_kind(copy doc),
@@ -323,12 +257,6 @@ fn write_mod(
     write_mod_contents(ctxt, ModDoc);
 }
 
-#[test]
-fn should_write_full_path_to_mod() {
-    let markdown = test::render(~"mod a { mod b { mod c { } } }");
-    assert!(str::contains(markdown, ~"# Module `a::b::c`"));
-}
-
 fn write_common(
     ctxt: &Ctxt,
     desc: Option<~str>,
@@ -363,17 +291,6 @@ fn write_section(ctxt: &Ctxt, section: doc::Section) {
     ctxt.w.put_line(~"");
 }
 
-#[test]
-fn should_write_sections() {
-    let markdown = test::render(
-        ~"#[doc = \"\
-         # Header\n\
-         Body\"]\
-         mod a {
-         }");
-    assert!(str::contains(markdown, ~"#### Header\n\nBody\n\n"));
-}
-
 fn write_mod_contents(
     ctxt: &Ctxt,
     doc: doc::ModDoc
@@ -402,15 +319,15 @@ fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) {
     }
 
     match doc {
-      doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc),
-      doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc),
-      doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc),
-      doc::ConstTag(ConstDoc) => write_const(ctxt, ConstDoc),
-      doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc),
-      doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc),
-      doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc),
-      doc::TyTag(TyDoc) => write_type(ctxt, TyDoc),
-      doc::StructTag(StructDoc) => put_struct(ctxt, StructDoc),
+        doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc),
+        doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc),
+        doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc),
+        doc::ConstTag(ConstDoc) => write_const(ctxt, ConstDoc),
+        doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc),
+        doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc),
+        doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc),
+        doc::TyTag(TyDoc) => write_type(ctxt, TyDoc),
+        doc::StructTag(StructDoc) => put_struct(ctxt, StructDoc),
     }
 }
 
@@ -420,17 +337,11 @@ fn write_item_header(ctxt: &Ctxt, doc: doc::ItemTag) {
 
 fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl {
     match doc {
-      &doc::ModTag(_) | &doc::NmodTag(_) => H1,
-      _ => H2
+        &doc::ModTag(_) | &doc::NmodTag(_) => H1,
+        _ => H2
     }
 }
 
-#[test]
-fn should_write_crate_description() {
-    let markdown = test::render(~"#[doc = \"this is the crate\"];");
-    assert!(str::contains(markdown, ~"this is the crate"));
-}
-
 fn write_index(ctxt: &Ctxt, index: doc::Index) {
     if vec::is_empty(index.entries) {
         return;
@@ -444,7 +355,7 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) {
         let id = copy entry.link;
         if entry.brief.is_some() {
             ctxt.w.put_line(fmt!("* [%s](%s) - %s",
-                                   header, id, (&entry.brief).get()));
+                                 header, id, (&entry.brief).get()));
         } else {
             ctxt.w.put_line(fmt!("* [%s](%s)", header, id));
         }
@@ -454,37 +365,6 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) {
     ctxt.w.put_line(~"");
 }
 
-#[test]
-fn should_write_index() {
-    let markdown = test::render(~"mod a { } mod b { }");
-    assert!(str::contains(
-        markdown,
-        ~"\n\n* [Module `a`](#module-a)\n\
-         * [Module `b`](#module-b)\n\n"
-    ));
-}
-
-#[test]
-fn should_write_index_brief() {
-    let markdown = test::render(~"#[doc = \"test\"] mod a { }");
-    assert!(str::contains(markdown, ~"(#module-a) - test\n"));
-}
-
-#[test]
-fn should_not_write_index_if_no_entries() {
-    let markdown = test::render(~"");
-    assert!(!str::contains(markdown, ~"\n\n\n"));
-}
-
-#[test]
-fn should_write_index_for_foreign_mods() {
-    let markdown = test::render(~"extern mod a { fn a(); }");
-    assert!(str::contains(
-        markdown,
-        ~"\n\n* [Function `a`](#function-a)\n\n"
-    ));
-}
-
 fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) {
     write_common(ctxt, doc.desc(), doc.sections());
     if doc.index.is_some() {
@@ -497,27 +377,6 @@ fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) {
     }
 }
 
-#[test]
-fn should_write_foreign_mods() {
-    let markdown = test::render(~"#[doc = \"test\"] extern mod a { }");
-    assert!(str::contains(markdown, ~"Foreign module `a`"));
-    assert!(str::contains(markdown, ~"test"));
-}
-
-#[test]
-fn should_write_foreign_fns() {
-    let markdown = test::render(
-        ~"extern mod a { #[doc = \"test\"] fn a(); }");
-    assert!(str::contains(markdown, ~"test"));
-}
-
-#[test]
-fn should_write_foreign_fn_headers() {
-    let markdown = test::render(
-        ~"extern mod a { #[doc = \"test\"] fn a(); }");
-    assert!(str::contains(markdown, ~"## Function `a`"));
-}
-
 fn write_fn(
     ctxt: &Ctxt,
     doc: doc::FnDoc
@@ -542,11 +401,11 @@ fn write_fnlike(
 
 fn write_sig(ctxt: &Ctxt, sig: Option<~str>) {
     match sig {
-      Some(sig) => {
-        ctxt.w.put_line(code_block_indent(sig));
-        ctxt.w.put_line(~"");
-      }
-      None => fail!(~"unimplemented")
+        Some(sig) => {
+            ctxt.w.put_line(code_block_indent(sig));
+            ctxt.w.put_line(~"");
+        }
+        None => fail!(~"unimplemented")
     }
 }
 
@@ -558,51 +417,6 @@ fn code_block_indent(s: ~str) -> ~str {
     str::connect(indented, "\n")
 }
 
-#[test]
-fn write_markdown_should_write_function_header() {
-    let markdown = test::render(~"fn func() { }");
-    assert!(str::contains(markdown, ~"## Function `func`"));
-}
-
-#[test]
-fn should_write_the_function_signature() {
-    let markdown = test::render(~"#[doc = \"f\"] fn a() { }");
-    assert!(str::contains(markdown, ~"\n    fn a()\n"));
-}
-
-#[test]
-fn should_insert_blank_line_after_fn_signature() {
-    let markdown = test::render(~"#[doc = \"f\"] fn a() { }");
-    assert!(str::contains(markdown, ~"fn a()\n\n"));
-}
-
-#[test]
-fn should_correctly_indent_fn_signature() {
-    let doc = test::create_doc(~"fn a() { }");
-    let doc = doc::Doc{
-        pages: ~[
-            doc::CratePage(doc::CrateDoc{
-                topmod: doc::ModDoc{
-                    items: ~[doc::FnTag(doc::SimpleItemDoc{
-                        sig: Some(~"line 1\nline 2"),
-                        .. copy doc.cratemod().fns()[0]
-                    })],
-                    .. doc.cratemod()
-                },
-                .. doc.CrateDoc()
-            })
-        ]
-    };
-    let markdown = test::write_markdown_str(doc);
-    assert!(str::contains(markdown, ~"    line 1\n    line 2"));
-}
-
-#[test]
-fn should_leave_blank_line_between_fn_header_and_sig() {
-    let markdown = test::render(~"fn a() { }");
-    assert!(str::contains(markdown, ~"Function `a`\n\n    fn a()"));
-}
-
 fn write_const(
     ctxt: &Ctxt,
     doc: doc::ConstDoc
@@ -611,20 +425,6 @@ fn write_const(
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
-#[test]
-fn should_write_const_header() {
-    let markdown = test::render(~"static a: bool = true;");
-    assert!(str::contains(markdown, ~"## Const `a`\n\n"));
-}
-
-#[test]
-fn should_write_const_description() {
-    let markdown = test::render(
-        ~"#[doc = \"b\"]\
-         static a: bool = true;");
-    assert!(str::contains(markdown, ~"\n\nb\n\n"));
-}
-
 fn write_enum(
     ctxt: &Ctxt,
     doc: doc::EnumDoc
@@ -633,19 +433,6 @@ fn write_enum(
     write_variants(ctxt, doc.variants);
 }
 
-#[test]
-fn should_write_enum_header() {
-    let markdown = test::render(~"enum a { b }");
-    assert!(str::contains(markdown, ~"## Enum `a`\n\n"));
-}
-
-#[test]
-fn should_write_enum_description() {
-    let markdown = test::render(
-        ~"#[doc = \"b\"] enum a { b }");
-    assert!(str::contains(markdown, ~"\n\nb\n\n"));
-}
-
 fn write_variants(
     ctxt: &Ctxt,
     docs: &[doc::VariantDoc]
@@ -667,46 +454,13 @@ fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) {
     assert!(doc.sig.is_some());
     let sig = (&doc.sig).get();
     match copy doc.desc {
-      Some(desc) => {
-        ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc));
-      }
-      None => {
-        ctxt.w.put_line(fmt!("* `%s`", sig));
-      }
-    }
-}
-
-#[test]
-fn should_write_variant_list() {
-    let markdown = test::render(
-        ~"enum a { \
-         #[doc = \"test\"] b, \
-         #[doc = \"test\"] c }");
-    assert!(str::contains(
-        markdown,
-        ~"\n\n#### Variants\n\
-         \n* `b` - test\
-         \n* `c` - test\n\n"));
-}
-
-#[test]
-fn should_write_variant_list_without_descs() {
-    let markdown = test::render(~"enum a { b, c }");
-    assert!(str::contains(
-        markdown,
-        ~"\n\n#### Variants\n\
-         \n* `b`\
-         \n* `c`\n\n"));
-}
-
-#[test]
-fn should_write_variant_list_with_signatures() {
-    let markdown = test::render(~"enum a { b(int), #[doc = \"a\"] c(int) }");
-    assert!(str::contains(
-        markdown,
-        ~"\n\n#### Variants\n\
-         \n* `b(int)`\
-         \n* `c(int)` - a\n\n"));
+        Some(desc) => {
+            ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc));
+        }
+        None => {
+            ctxt.w.put_line(fmt!("* `%s`", sig));
+        }
+    }
 }
 
 fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) {
@@ -730,78 +484,11 @@ fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) {
     );
 }
 
-#[test]
-fn should_write_trait_header() {
-    let markdown = test::render(~"trait i { fn a(); }");
-    assert!(str::contains(markdown, ~"## Trait `i`"));
-}
-
-#[test]
-fn should_write_trait_desc() {
-    let markdown = test::render(
-        ~"#[doc = \"desc\"] trait i { fn a(); }");
-    assert!(str::contains(markdown, ~"desc"));
-}
-
-#[test]
-fn should_write_trait_method_header() {
-    let markdown = test::render(
-        ~"trait i { fn a(); }");
-    assert!(str::contains(markdown, ~"### Method `a`"));
-}
-
-#[test]
-fn should_write_trait_method_signature() {
-    let markdown = test::render(
-        ~"trait i { fn a(&self); }");
-    assert!(str::contains(markdown, ~"\n    fn a(&self)"));
-}
-
 fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) {
     write_common(ctxt, doc.desc(), doc.sections());
     write_methods(ctxt, doc.methods);
 }
 
-#[test]
-fn should_write_impl_header() {
-    let markdown = test::render(~"impl int { fn a() { } }");
-    assert!(str::contains(markdown, ~"## Implementation for `int`"));
-}
-
-#[test]
-fn should_write_impl_header_with_bounds() {
-    let markdown = test::render(~"impl <T> int<T> { }");
-    assert!(str::contains(markdown, ~"## Implementation for `int<T>` where `<T>`"));
-}
-
-#[test]
-fn should_write_impl_header_with_trait() {
-    let markdown = test::render(~"impl j for int { fn a() { } }");
-    assert!(str::contains(markdown,
-        ~"## Implementation of `j` for `int`"));
-}
-
-#[test]
-fn should_write_impl_desc() {
-    let markdown = test::render(
-        ~"#[doc = \"desc\"] impl int { fn a() { } }");
-    assert!(str::contains(markdown, ~"desc"));
-}
-
-#[test]
-fn should_write_impl_method_header() {
-    let markdown = test::render(
-        ~"impl int { fn a() { } }");
-    assert!(str::contains(markdown, ~"### Method `a`"));
-}
-
-#[test]
-fn should_write_impl_method_signature() {
-    let markdown = test::render(
-        ~"impl int { fn a(&mut self) { } }");
-    assert!(str::contains(markdown, ~"\n    fn a(&mut self)"));
-}
-
 fn write_type(
     ctxt: &Ctxt,
     doc: doc::TyDoc
@@ -810,25 +497,6 @@ fn write_type(
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
-#[test]
-fn should_write_type_header() {
-    let markdown = test::render(~"type t = int;");
-    assert!(str::contains(markdown, ~"## Type `t`"));
-}
-
-#[test]
-fn should_write_type_desc() {
-    let markdown = test::render(
-        ~"#[doc = \"desc\"] type t = int;");
-    assert!(str::contains(markdown, ~"\n\ndesc\n\n"));
-}
-
-#[test]
-fn should_write_type_signature() {
-    let markdown = test::render(~"type t = int;");
-    assert!(str::contains(markdown, ~"\n\n    type t = int\n\n"));
-}
-
 fn put_struct(
     ctxt: &Ctxt,
     doc: doc::StructDoc
@@ -837,12 +505,6 @@ fn put_struct(
     write_common(ctxt, doc.desc(), doc.sections());
 }
 
-#[test]
-fn should_put_struct_header() {
-    let markdown = test::render(~"struct S { field: () }");
-    assert!(str::contains(markdown, ~"## Struct `S`\n\n"));
-}
-
 #[cfg(test)]
 mod test {
     use astsrv;
@@ -855,22 +517,21 @@ mod test {
     use markdown_pass::{mk_pass, write_markdown};
     use markdown_writer;
     use path_pass;
+    use page_pass;
     use sectionalize_pass;
     use trim_pass;
     use tystr_pass;
     use unindent_pass;
+    use core::prelude::*;
 
-    use core::path::Path;
-    use core::str;
-
-    pub fn render(source: ~str) -> ~str {
+    fn render(source: ~str) -> ~str {
         let (srv, doc) = create_doc_srv(source);
         let markdown = write_markdown_str_srv(srv, doc);
         debug!("markdown: %s", markdown);
         markdown
     }
 
-    pub fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) {
+    fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) {
         do astsrv::from_str(source) |srv| {
 
             let config = config::Config {
@@ -901,12 +562,12 @@ mod test {
         }
     }
 
-    pub fn create_doc(source: ~str) -> doc::Doc {
+    fn create_doc(source: ~str) -> doc::Doc {
         let (_, doc) = create_doc_srv(source);
         doc
     }
 
-    pub fn write_markdown_str(
+    fn write_markdown_str(
         doc: doc::Doc
     ) -> ~str {
         let (writer_factory, po) = markdown_writer::future_writer_factory();
@@ -914,7 +575,7 @@ mod test {
         return po.recv().second();
     }
 
-    pub fn write_markdown_str_srv(
+    fn write_markdown_str_srv(
         srv: astsrv::Srv,
         doc: doc::Doc
     ) -> ~str {
@@ -925,14 +586,349 @@ mod test {
     }
 
     #[test]
-    pub fn write_markdown_should_write_mod_headers() {
+    fn write_markdown_should_write_mod_headers() {
         let markdown = render(~"mod moo { }");
         assert!(str::contains(markdown, ~"# Module `moo`"));
     }
 
     #[test]
-    pub fn should_leave_blank_line_after_header() {
+    fn should_leave_blank_line_after_header() {
         let markdown = render(~"mod morp { }");
         assert!(str::contains(markdown, ~"Module `morp`\n\n"));
     }
+
+    #[test]
+    fn should_write_modules_last() {
+        /*
+        Because the markdown pass writes all modules at the same level of
+        indentation (it doesn't 'nest' them), we need to make sure that we
+        write all of the modules contained in each module after all other
+        types of items, or else the header nesting will end up wrong, with
+        modules appearing to contain items that they do not.
+        */
+        let markdown = render(
+            ~"mod a { }\
+              fn b() { }\
+              mod c {
+}\
+              fn d() { }"
+        );
+
+        let idx_a = str::find_str(markdown, ~"# Module `a`").get();
+        let idx_b = str::find_str(markdown, ~"## Function `b`").get();
+        let idx_c = str::find_str(markdown, ~"# Module `c`").get();
+        let idx_d = str::find_str(markdown, ~"## Function `d`").get();
+
+        assert!(idx_b < idx_d);
+        assert!(idx_d < idx_a);
+        assert!(idx_a < idx_c);
+    }
+
+    #[test]
+    fn should_request_new_writer_for_each_page() {
+        // This port will send us a (page, str) pair for every writer
+        // that was created
+        let (writer_factory, po) = markdown_writer::future_writer_factory();
+        let (srv, doc) = create_doc_srv(~"mod a { }");
+        // Split the document up into pages
+        let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
+        write_markdown(doc, writer_factory);
+        // We expect two pages to have been written
+        for iter::repeat(2) {
+            po.recv();
+        }
+    }
+
+    #[test]
+    fn should_write_title_for_each_page() {
+        let (writer_factory, po) = markdown_writer::future_writer_factory();
+        let (srv, doc) = create_doc_srv(
+            ~"#[link(name = \"core\")]; mod a { }");
+        let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
+        write_markdown(doc, writer_factory);
+        for iter::repeat(2) {
+            let (page, markdown) = po.recv();
+            match page {
+                doc::CratePage(_) => {
+                    assert!(str::contains(markdown, ~"% Crate core"));
+                }
+                doc::ItemPage(_) => {
+                    assert!(str::contains(markdown, ~"% Module a"));
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn should_write_full_path_to_mod() {
+        let markdown = render(~"mod a { mod b { mod c { } } }");
+        assert!(str::contains(markdown, ~"# Module `a::b::c`"));
+    }
+
+    #[test]
+    fn should_write_sections() {
+        let markdown = render(
+            ~"#[doc = \"\
+              # Header\n\
+              Body\"]\
+              mod a {
+}");
+        assert!(str::contains(markdown, ~"#### Header\n\nBody\n\n"));
+    }
+
+    #[test]
+    fn should_write_crate_description() {
+        let markdown = render(~"#[doc = \"this is the crate\"];");
+        assert!(str::contains(markdown, ~"this is the crate"));
+    }
+
+
+    #[test]
+    fn should_write_index() {
+        let markdown = render(~"mod a { } mod b { }");
+        assert!(str::contains(
+            markdown,
+            ~"\n\n* [Module `a`](#module-a)\n\
+              * [Module `b`](#module-b)\n\n"
+        ));
+    }
+
+    #[test]
+    fn should_write_index_brief() {
+        let markdown = render(~"#[doc = \"test\"] mod a { }");
+        assert!(str::contains(markdown, ~"(#module-a) - test\n"));
+    }
+
+    #[test]
+    fn should_not_write_index_if_no_entries() {
+        let markdown = render(~"");
+        assert!(!str::contains(markdown, ~"\n\n\n"));
+    }
+
+    #[test]
+    fn should_write_index_for_foreign_mods() {
+        let markdown = render(~"extern mod a { fn a(); }");
+        assert!(str::contains(
+            markdown,
+            ~"\n\n* [Function `a`](#function-a)\n\n"
+        ));
+    }
+
+    #[test]
+    fn should_write_foreign_mods() {
+        let markdown = render(~"#[doc = \"test\"] extern mod a { }");
+        assert!(str::contains(markdown, ~"Foreign module `a`"));
+        assert!(str::contains(markdown, ~"test"));
+    }
+
+    #[test]
+    fn should_write_foreign_fns() {
+        let markdown = render(
+            ~"extern mod a { #[doc = \"test\"] fn a(); }");
+        assert!(str::contains(markdown, ~"test"));
+    }
+
+    #[test]
+    fn should_write_foreign_fn_headers() {
+        let markdown = render(
+            ~"extern mod a { #[doc = \"test\"] fn a(); }");
+        assert!(str::contains(markdown, ~"## Function `a`"));
+    }
+
+    #[test]
+    fn write_markdown_should_write_function_header() {
+        let markdown = render(~"fn func() { }");
+        assert!(str::contains(markdown, ~"## Function `func`"));
+    }
+
+    #[test]
+    fn should_write_the_function_signature() {
+        let markdown = render(~"#[doc = \"f\"] fn a() { }");
+        assert!(str::contains(markdown, ~"\n    fn a()\n"));
+    }
+
+    #[test]
+    fn should_insert_blank_line_after_fn_signature() {
+        let markdown = render(~"#[doc = \"f\"] fn a() { }");
+        assert!(str::contains(markdown, ~"fn a()\n\n"));
+    }
+
+    #[test]
+    fn should_correctly_indent_fn_signature() {
+        let doc = create_doc(~"fn a() { }");
+        let doc = doc::Doc{
+            pages: ~[
+                doc::CratePage(doc::CrateDoc{
+                    topmod: doc::ModDoc{
+                        items: ~[doc::FnTag(doc::SimpleItemDoc{
+                            sig: Some(~"line 1\nline 2"),
+                            .. copy doc.cratemod().fns()[0]
+                        })],
+                        .. doc.cratemod()
+                    },
+                    .. doc.CrateDoc()
+                })
+            ]
+        };
+        let markdown = write_markdown_str(doc);
+        assert!(str::contains(markdown, ~"    line 1\n    line 2"));
+    }
+
+    #[test]
+    fn should_leave_blank_line_between_fn_header_and_sig() {
+        let markdown = render(~"fn a() { }");
+        assert!(str::contains(markdown, ~"Function `a`\n\n    fn a()"));
+    }
+
+    #[test]
+    fn should_write_const_header() {
+        let markdown = render(~"static a: bool = true;");
+        assert!(str::contains(markdown, ~"## Const `a`\n\n"));
+    }
+
+    #[test]
+    fn should_write_const_description() {
+        let markdown = render(
+            ~"#[doc = \"b\"]\
+              static a: bool = true;");
+        assert!(str::contains(markdown, ~"\n\nb\n\n"));
+    }
+
+    #[test]
+    fn should_write_enum_header() {
+        let markdown = render(~"enum a { b }");
+        assert!(str::contains(markdown, ~"## Enum `a`\n\n"));
+    }
+
+    #[test]
+    fn should_write_enum_description() {
+        let markdown = render(
+            ~"#[doc = \"b\"] enum a { b }");
+        assert!(str::contains(markdown, ~"\n\nb\n\n"));
+    }
+
+    #[test]
+    fn should_write_variant_list() {
+        let markdown = render(
+            ~"enum a { \
+              #[doc = \"test\"] b, \
+              #[doc = \"test\"] c }");
+        assert!(str::contains(
+            markdown,
+            ~"\n\n#### Variants\n\
+              \n* `b` - test\
+              \n* `c` - test\n\n"));
+    }
+
+    #[test]
+    fn should_write_variant_list_without_descs() {
+        let markdown = render(~"enum a { b, c }");
+        assert!(str::contains(
+            markdown,
+            ~"\n\n#### Variants\n\
+              \n* `b`\
+              \n* `c`\n\n"));
+    }
+
+    #[test]
+    fn should_write_variant_list_with_signatures() {
+        let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }");
+        assert!(str::contains(
+            markdown,
+            ~"\n\n#### Variants\n\
+              \n* `b(int)`\
+              \n* `c(int)` - a\n\n"));
+    }
+
+    #[test]
+    fn should_write_trait_header() {
+        let markdown = render(~"trait i { fn a(); }");
+        assert!(str::contains(markdown, ~"## Trait `i`"));
+    }
+
+    #[test]
+    fn should_write_trait_desc() {
+        let markdown = render(
+            ~"#[doc = \"desc\"] trait i { fn a(); }");
+        assert!(str::contains(markdown, ~"desc"));
+    }
+
+    #[test]
+    fn should_write_trait_method_header() {
+        let markdown = render(
+            ~"trait i { fn a(); }");
+        assert!(str::contains(markdown, ~"### Method `a`"));
+    }
+
+    #[test]
+    fn should_write_trait_method_signature() {
+        let markdown = render(
+            ~"trait i { fn a(&self); }");
+        assert!(str::contains(markdown, ~"\n    fn a(&self)"));
+    }
+
+    #[test]
+    fn should_write_impl_header() {
+        let markdown = render(~"impl int { fn a() { } }");
+        assert!(str::contains(markdown, ~"## Implementation for `int`"));
+    }
+
+    #[test]
+    fn should_write_impl_header_with_bounds() {
+        let markdown = render(~"impl <T> int<T> { }");
+        assert!(str::contains(markdown, ~"## Implementation for `int<T>` where `<T>`"));
+    }
+
+    #[test]
+    fn should_write_impl_header_with_trait() {
+        let markdown = render(~"impl j for int { fn a() { } }");
+        assert!(str::contains(markdown,
+                              ~"## Implementation of `j` for `int`"));
+    }
+
+    #[test]
+    fn should_write_impl_desc() {
+        let markdown = render(
+            ~"#[doc = \"desc\"] impl int { fn a() { } }");
+        assert!(str::contains(markdown, ~"desc"));
+    }
+
+    #[test]
+    fn should_write_impl_method_header() {
+        let markdown = render(
+            ~"impl int { fn a() { } }");
+        assert!(str::contains(markdown, ~"### Method `a`"));
+    }
+
+    #[test]
+    fn should_write_impl_method_signature() {
+        let markdown = render(
+            ~"impl int { fn a(&mut self) { } }");
+        assert!(str::contains(markdown, ~"\n    fn a(&mut self)"));
+    }
+
+    #[test]
+    fn should_write_type_header() {
+        let markdown = render(~"type t = int;");
+        assert!(str::contains(markdown, ~"## Type `t`"));
+    }
+
+    #[test]
+    fn should_write_type_desc() {
+        let markdown = render(
+            ~"#[doc = \"desc\"] type t = int;");
+        assert!(str::contains(markdown, ~"\n\ndesc\n\n"));
+    }
+
+    #[test]
+    fn should_write_type_signature() {
+        let markdown = render(~"type t = int;");
+        assert!(str::contains(markdown, ~"\n\n    type t = int\n\n"));
+    }
+
+    #[test]
+    fn should_put_struct_header() {
+        let markdown = render(~"struct S { field: () }");
+        assert!(str::contains(markdown, ~"## Struct `S`\n\n"));
+    }
 }