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.rs941
1 files changed, 0 insertions, 941 deletions
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
deleted file mode 100644
index 7d07b4864f5..00000000000
--- a/src/librustdoc/markdown_pass.rs
+++ /dev/null
@@ -1,941 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Generate markdown from a document tree
-
-
-use astsrv;
-use doc::ItemUtils;
-use doc;
-use markdown_pass;
-use markdown_writer::Writer;
-use markdown_writer::WriterUtils;
-use markdown_writer::WriterFactory;
-use pass::Pass;
-use sort_pass;
-
-use std::cell::Cell;
-use std::str;
-use std::vec;
-use syntax;
-
-pub fn mk_pass(writer_factory: WriterFactory) -> Pass {
-    let writer_factory = Cell::new(writer_factory);
-    Pass {
-        name: ~"markdown",
-        f: |srv, doc| run(srv, doc, writer_factory.take())
-    }
-}
-
-fn run(
-    srv: astsrv::Srv,
-    doc: doc::Doc,
-    writer_factory: WriterFactory
-) -> doc::Doc {
-
-    fn mods_last(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool {
-        fn is_mod(item: &doc::ItemTag) -> bool {
-            match *item {
-                doc::ModTag(_) => true,
-                _ => false
-            }
-        }
-
-        let lteq = !is_mod(item1) || is_mod(item2);
-        lteq
-    }
-
-    // Sort the items so mods come last. All mods will be
-    // output at the same header level so sorting mods last
-    // makes the headers come out nested correctly.
-    let sorted_doc = (sort_pass::mk_pass(
-        ~"mods last", mods_last
-    ).f)(srv, doc.clone());
-
-    write_markdown(sorted_doc, writer_factory);
-
-    return doc;
-}
-
-struct Ctxt {
-    w: Writer
-}
-
-pub fn write_markdown(
-    doc: doc::Doc,
-    writer_factory: WriterFactory
-) {
-    // There is easy parallelism to be had here, but
-    // we don't want to spawn too many pandoc processes.
-    // (See #2484, which is closed.)
-    do doc.pages.map |page| {
-        let ctxt = Ctxt {
-            w: writer_factory((*page).clone())
-        };
-        write_page(&ctxt, page)
-    };
-}
-
-fn write_page(ctxt: &Ctxt, page: &doc::Page) {
-    write_title(ctxt, (*page).clone());
-    match (*page).clone() {
-        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();
-}
-
-fn write_title(ctxt: &Ctxt, page: doc::Page) {
-    ctxt.w.put_line(fmt!("%% %s", make_title(page)));
-    ctxt.w.put_line(~"");
-}
-
-fn make_title(page: doc::Page) -> ~str {
-    let item = match page {
-        doc::CratePage(CrateDoc) => {
-            doc::ModTag(CrateDoc.topmod.clone())
-        }
-        doc::ItemPage(ItemTag) => {
-            ItemTag
-        }
-    };
-    let title = markdown_pass::header_text(item);
-    let title = title.replace("`", "");
-    return title;
-}
-
-enum Hlvl {
-    H1 = 1,
-    H2 = 2,
-    H3 = 3,
-    H4 = 4
-}
-
-fn write_header(ctxt: &Ctxt, lvl: Hlvl, doc: doc::ItemTag) {
-    let text = header_text(doc);
-    write_header_(ctxt, lvl, text);
-}
-
-fn write_header_(ctxt: &Ctxt, lvl: Hlvl, title: ~str) {
-    let hashes = str::from_chars(vec::from_elem(lvl as uint, '#'));
-    ctxt.w.put_line(fmt!("%s %s", hashes, title));
-    ctxt.w.put_line(~"");
-}
-
-pub fn header_kind(doc: doc::ItemTag) -> ~str {
-    match doc {
-        doc::ModTag(_) => {
-            if doc.id() == syntax::ast::CRATE_NODE_ID {
-                ~"Crate"
-            } else {
-                ~"Module"
-            }
-        }
-        doc::NmodTag(_) => {
-            ~"Foreign module"
-        }
-        doc::FnTag(_) => {
-            ~"Function"
-        }
-        doc::StaticTag(_) => {
-            ~"Static"
-        }
-        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 = (doc.path() + &[doc.name_()]).connect("::");
-    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_ref())
-            } else {
-                ~""
-            };
-            let self_ty = doc.self_ty.get_ref();
-            let mut trait_part = ~"";
-            for (i, trait_type) in doc.trait_types.iter().enumerate() {
-                if i == 0 {
-                    trait_part.push_str(" of ");
-                } else {
-                    trait_part.push_str(", ");
-                }
-                trait_part.push_str(*trait_type);
-            }
-            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(doc.clone());
-            let bounds = if ImplDoc.bounds_str.is_some() {
-                fmt!(" where `%s`", *ImplDoc.bounds_str.get_ref())
-            } else {
-                ~""
-            };
-            let desc = if ImplDoc.trait_types.is_empty() {
-                fmt!("for `%s`%s", *ImplDoc.self_ty.get_ref(), bounds)
-            } else {
-                fmt!("of `%s` for `%s`%s",
-                     ImplDoc.trait_types[0],
-                     *ImplDoc.self_ty.get_ref(),
-                     bounds)
-            };
-            return fmt!("%s %s", header_kind, desc);
-        }
-        _ => {}
-    }
-
-    header_text_(header_kind(doc.clone()),
-                 header_name(doc))
-}
-
-fn header_text_(kind: &str, name: &str) -> ~str {
-    fmt!("%s `%s`", kind, name)
-}
-
-fn write_crate(
-    ctxt: &Ctxt,
-    doc: doc::CrateDoc
-) {
-    write_top_module(ctxt, doc.topmod.clone());
-}
-
-fn write_top_module(
-    ctxt: &Ctxt,
-    ModDoc: doc::ModDoc
-) {
-    write_mod_contents(ctxt, ModDoc);
-}
-
-fn write_mod(
-    ctxt: &Ctxt,
-    ModDoc: doc::ModDoc
-) {
-    write_mod_contents(ctxt, ModDoc);
-}
-
-fn write_common(
-    ctxt: &Ctxt,
-    desc: Option<~str>,
-    sections: &[doc::Section]
-) {
-    write_desc(ctxt, desc);
-    write_sections(ctxt, sections);
-}
-
-fn write_desc(
-    ctxt: &Ctxt,
-    desc: Option<~str>
-) {
-    match desc {
-        Some(desc) => {
-            ctxt.w.put_line(desc);
-            ctxt.w.put_line(~"");
-        }
-        None => ()
-    }
-}
-
-fn write_sections(ctxt: &Ctxt, sections: &[doc::Section]) {
-    for section in sections.iter() {
-        write_section(ctxt, (*section).clone());
-    }
-}
-
-fn write_section(ctxt: &Ctxt, section: doc::Section) {
-    write_header_(ctxt, H4, section.header.clone());
-    ctxt.w.put_line(section.body.clone());
-    ctxt.w.put_line(~"");
-}
-
-fn write_mod_contents(
-    ctxt: &Ctxt,
-    doc: doc::ModDoc
-) {
-    write_common(ctxt, doc.desc(), doc.sections());
-    if doc.index.is_some() {
-        write_index(ctxt, doc.index.get_ref());
-    }
-
-    for itemTag in doc.items.iter() {
-        write_item(ctxt, (*itemTag).clone());
-    }
-}
-
-fn write_item(ctxt: &Ctxt, doc: doc::ItemTag) {
-    write_item_(ctxt, doc, true);
-}
-
-fn write_item_no_header(ctxt: &Ctxt, doc: doc::ItemTag) {
-    write_item_(ctxt, doc, false);
-}
-
-fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) {
-    if write_header {
-        write_item_header(ctxt, doc.clone());
-    }
-
-    match doc {
-        doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc),
-        doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc),
-        doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc),
-        doc::StaticTag(StaticDoc) => write_static(ctxt, StaticDoc),
-        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),
-    }
-}
-
-fn write_item_header(ctxt: &Ctxt, doc: doc::ItemTag) {
-    write_header(ctxt, item_header_lvl(&doc), doc);
-}
-
-fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl {
-    match doc {
-        &doc::ModTag(_) | &doc::NmodTag(_) => H1,
-        _ => H2
-    }
-}
-
-fn write_index(ctxt: &Ctxt, index: &doc::Index) {
-    if index.entries.is_empty() {
-        return;
-    }
-
-    ctxt.w.put_line(~"<div class='index'>");
-    ctxt.w.put_line(~"");
-
-    for entry in index.entries.iter() {
-        let header = header_text_(entry.kind, entry.name);
-        let id = entry.link.clone();
-        if entry.brief.is_some() {
-            ctxt.w.put_line(fmt!("* [%s](%s) - %s",
-                                 header, id, *entry.brief.get_ref()));
-        } else {
-            ctxt.w.put_line(fmt!("* [%s](%s)", header, id));
-        }
-    }
-    ctxt.w.put_line(~"");
-    ctxt.w.put_line(~"</div>");
-    ctxt.w.put_line(~"");
-}
-
-fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) {
-    write_common(ctxt, doc.desc(), doc.sections());
-    if doc.index.is_some() {
-        write_index(ctxt, doc.index.get_ref());
-    }
-
-    for FnDoc in doc.fns.iter() {
-        write_item_header(ctxt, doc::FnTag((*FnDoc).clone()));
-        write_fn(ctxt, (*FnDoc).clone());
-    }
-}
-
-fn write_fn(
-    ctxt: &Ctxt,
-    doc: doc::FnDoc
-) {
-    write_fnlike(ctxt, doc.sig.clone(), doc.desc(), doc.sections());
-}
-
-fn write_fnlike(
-    ctxt: &Ctxt,
-    sig: Option<~str>,
-    desc: Option<~str>,
-    sections: &[doc::Section]
-) {
-    write_sig(ctxt, sig);
-    write_common(ctxt, desc, sections);
-}
-
-fn write_sig(ctxt: &Ctxt, sig: Option<~str>) {
-    match sig {
-        Some(sig) => {
-            ctxt.w.put_line(code_block(sig));
-            ctxt.w.put_line(~"");
-        }
-        None => fail!("unimplemented")
-    }
-}
-
-fn code_block(s: ~str) -> ~str {
-    fmt!("~~~ {.rust}
-%s
-~~~", s)
-}
-
-fn write_static(
-    ctxt: &Ctxt,
-    doc: doc::StaticDoc
-) {
-    write_sig(ctxt, doc.sig.clone());
-    write_common(ctxt, doc.desc(), doc.sections());
-}
-
-fn write_enum(
-    ctxt: &Ctxt,
-    doc: doc::EnumDoc
-) {
-    write_common(ctxt, doc.desc(), doc.sections());
-    write_variants(ctxt, doc.variants);
-}
-
-fn write_variants(
-    ctxt: &Ctxt,
-    docs: &[doc::VariantDoc]
-) {
-    if docs.is_empty() {
-        return;
-    }
-
-    write_header_(ctxt, H4, ~"Variants");
-
-    for variant in docs.iter() {
-        write_variant(ctxt, (*variant).clone());
-    }
-
-    ctxt.w.put_line(~"");
-}
-
-fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) {
-    assert!(doc.sig.is_some());
-    let sig = doc.sig.get_ref();
-
-    // space out list items so they all end up within paragraph elements
-    ctxt.w.put_line(~"");
-
-    match doc.desc.clone() {
-        Some(desc) => {
-            ctxt.w.put_line(list_item_indent(fmt!("* `%s` - %s", *sig, desc)));
-        }
-        None => {
-            ctxt.w.put_line(fmt!("* `%s`", *sig));
-        }
-    }
-}
-
-fn list_item_indent(item: &str) -> ~str {
-    let indented = item.any_line_iter().collect::<~[&str]>();
-
-    // separate markdown elements within `*` lists must be indented by four
-    // spaces, or they will escape the list context. indenting everything
-    // seems fine though.
-    indented.connect("\n    ")
-}
-
-fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) {
-    write_common(ctxt, doc.desc(), doc.sections());
-    write_methods(ctxt, doc.methods);
-}
-
-fn write_methods(ctxt: &Ctxt, docs: &[doc::MethodDoc]) {
-    for doc in docs.iter() {
-        write_method(ctxt, (*doc).clone());
-    }
-}
-
-fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) {
-    write_header_(ctxt, H3, header_text_("Method", doc.name));
-    write_fnlike(ctxt, doc.sig.clone(), doc.desc.clone(), doc.sections);
-}
-
-fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) {
-    write_common(ctxt, doc.desc(), doc.sections());
-    write_methods(ctxt, doc.methods);
-}
-
-fn write_type(
-    ctxt: &Ctxt,
-    doc: doc::TyDoc
-) {
-    write_sig(ctxt, doc.sig.clone());
-    write_common(ctxt, doc.desc(), doc.sections());
-}
-
-fn put_struct(
-    ctxt: &Ctxt,
-    doc: doc::StructDoc
-) {
-    write_sig(ctxt, doc.sig.clone());
-    write_common(ctxt, doc.desc(), doc.sections());
-}
-
-#[cfg(test)]
-mod test {
-
-    use astsrv;
-    use attr_pass;
-    use config;
-    use desc_to_brief_pass;
-    use doc;
-    use extract;
-    use markdown_index_pass;
-    use markdown_pass::{mk_pass, write_markdown};
-    use markdown_writer;
-    use path_pass;
-    use page_pass;
-    use prune_hidden_pass;
-    use sectionalize_pass;
-    use trim_pass;
-    use tystr_pass;
-    use unindent_pass;
-
-    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
-    }
-
-    fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) {
-        do astsrv::from_str(source) |srv| {
-
-            let config = config::Config {
-                output_style: config::DocPerCrate,
-                .. config::default_config(&Path("whatever"))
-            };
-
-            let doc = extract::from_srv(srv.clone(), ~"");
-            debug!("doc (extract): %?", doc);
-            let doc = (tystr_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (tystr): %?", doc);
-            let doc = (path_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (path): %?", doc);
-            let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (attr): %?", doc);
-            let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (prune_hidden): %?", doc);
-            let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (desc_to_brief): %?", doc);
-            let doc = (unindent_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (unindent): %?", doc);
-            let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (trim): %?", doc);
-            let doc = (trim_pass::mk_pass().f)(srv.clone(), doc);
-            debug!("doc (sectionalize): %?", doc);
-            let doc = (markdown_index_pass::mk_pass(config).f)(
-                srv.clone(), doc);
-            debug!("doc (index): %?", doc);
-            (srv.clone(), doc)
-        }
-    }
-
-    fn create_doc(source: ~str) -> doc::Doc {
-        let (_, doc) = create_doc_srv(source);
-        doc
-    }
-
-    fn write_markdown_str(
-        doc: doc::Doc
-    ) -> ~str {
-        let (writer_factory, po) = markdown_writer::future_writer_factory();
-        write_markdown(doc, writer_factory);
-        return po.recv().second();
-    }
-
-    fn write_markdown_str_srv(
-        srv: astsrv::Srv,
-        doc: doc::Doc
-    ) -> ~str {
-        let (writer_factory, po) = markdown_writer::future_writer_factory();
-        let pass = mk_pass(writer_factory);
-        (pass.f)(srv, doc);
-        return po.recv().second();
-    }
-
-    #[test]
-    fn write_markdown_should_write_mod_headers() {
-        let markdown = render(~"mod moo { }");
-        assert!(markdown.contains("# Module `moo`"));
-    }
-
-    #[test]
-    fn should_leave_blank_line_after_header() {
-        let markdown = render(~"mod morp { }");
-        assert!(markdown.contains("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 = markdown.find_str("# Module `a`").unwrap();
-        let idx_b = markdown.find_str("## Function `b`").unwrap();
-        let idx_c = markdown.find_str("# Module `c`").unwrap();
-        let idx_d = markdown.find_str("## Function `d`").unwrap();
-
-        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 _ in range(0, 2u) {
-            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 _ in range(0, 2u) {
-            let (page, markdown) = po.recv();
-            match page {
-                doc::CratePage(_) => {
-                    assert!(markdown.contains("% Crate core"));
-                }
-                doc::ItemPage(_) => {
-                    assert!(markdown.contains("% Module a"));
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn should_write_full_path_to_mod() {
-        let markdown = render(~"mod a { mod b { mod c { } } }");
-        assert!(markdown.contains("# Module `a::b::c`"));
-    }
-
-    #[test]
-    fn should_write_sections() {
-        let markdown = render(
-            ~"#[doc = \"\
-              # Header\n\
-              Body\"]\
-              mod a {
-}");
-        assert!(markdown.contains("#### Header\n\nBody\n\n"));
-    }
-
-    #[test]
-    fn should_write_crate_description() {
-        let markdown = render(~"#[doc = \"this is the crate\"];");
-        assert!(markdown.contains("this is the crate"));
-    }
-
-
-    #[test]
-    fn should_write_index() {
-        let markdown = render(~"mod a { } mod b { }");
-        assert!(markdown.contains(
-            "\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!(markdown.contains("(#module-a) - test\n"));
-    }
-
-    #[test]
-    fn should_not_write_index_if_no_entries() {
-        let markdown = render(~"");
-        assert!(!markdown.contains("\n\n\n"));
-    }
-
-    #[test]
-    fn should_write_index_for_foreign_mods() {
-        let markdown = render(~"extern { fn a(); }");
-        assert!(markdown.contains(
-            "\n\n* [Function `a`](#function-a)\n\n"
-        ));
-    }
-
-    #[test]
-    fn should_write_foreign_fns() {
-        let markdown = render(
-            ~"extern { #[doc = \"test\"] fn a(); }");
-        assert!(markdown.contains("test"));
-    }
-
-    #[test]
-    fn should_write_foreign_fn_headers() {
-        let markdown = render(
-            ~"extern { #[doc = \"test\"] fn a(); }");
-        assert!(markdown.contains("## Function `a`"));
-    }
-
-    #[test]
-    fn write_markdown_should_write_function_header() {
-        let markdown = render(~"fn func() { }");
-        assert!(markdown.contains("## Function `func`"));
-    }
-
-    #[test]
-    fn should_write_the_function_signature() {
-        let markdown = render(~"#[doc = \"f\"] fn a() { }");
-        assert!(markdown.contains("\n~~~ {.rust}\nfn a()\n"));
-    }
-
-    #[test]
-    fn should_insert_blank_line_after_fn_signature() {
-        let markdown = render(~"#[doc = \"f\"] fn a() { }");
-        assert!(markdown.contains("fn a()\n~~~\n\n"));
-    }
-
-    #[test]
-    fn should_correctly_bracket_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"),
-                            .. (doc.cratemod().fns()[0]).clone()
-                        })],
-                        .. doc.cratemod()
-                    },
-                    .. doc.CrateDoc()
-                })
-            ]
-        };
-        let markdown = write_markdown_str(doc);
-        assert!(markdown.contains("~~~ {.rust}\nline 1\nline 2\n~~~"));
-    }
-
-    #[test]
-    fn should_leave_blank_line_between_fn_header_and_sig() {
-        let markdown = render(~"fn a() { }");
-        assert!(markdown.contains("Function `a`\n\n~~~ {.rust}\nfn a()"));
-    }
-
-    #[test]
-    fn should_write_static_header() {
-        let markdown = render(~"static a: bool = true;");
-        assert!(markdown.contains("## Static `a`\n\n"));
-    }
-
-    #[test]
-    fn should_write_static_description() {
-        let markdown = render(
-            ~"#[doc = \"b\"]\
-              static a: bool = true;");
-        assert!(markdown.contains("\n\nb\n\n"));
-    }
-
-    #[test]
-    fn should_write_enum_header() {
-        let markdown = render(~"enum a { b }");
-        assert!(markdown.contains("## Enum `a`\n\n"));
-    }
-
-    #[test]
-    fn should_write_enum_description() {
-        let markdown = render(~"#[doc = \"b\"] enum a { b }");
-        assert!(markdown.contains("\n\nb\n\n"));
-    }
-
-    #[test]
-    fn should_write_variant_list() {
-        let markdown = render(
-            ~"enum a { \
-              #[doc = \"test\"] b, \
-              #[doc = \"test\"] c }");
-        assert!(markdown.contains(
-            "\n\n#### Variants\n\
-             \n\
-             \n* `b` - test\
-             \n\
-             \n* `c` - test\n\n"));
-    }
-
-    #[test]
-    fn should_write_variant_list_without_descs() {
-        let markdown = render(~"enum a { b, c }");
-        assert!(markdown.contains(
-            "\n\n#### Variants\n\
-             \n\
-             \n* `b`\
-             \n\
-             \n* `c`\n\n"));
-    }
-
-    #[test]
-    fn should_write_variant_list_with_indent() {
-        let markdown = render(
-            ~"enum a { #[doc = \"line 1\\n\\nline 2\"] b, c }");
-        assert!(markdown.contains(
-            "\n\n#### Variants\n\
-             \n\
-             \n* `b` - line 1\
-             \n    \
-             \n    line 2\
-             \n\
-             \n* `c`\n\n"));
-    }
-
-    #[test]
-    fn should_write_variant_list_with_signatures() {
-        let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }");
-        assert!(markdown.contains(
-            "\n\n#### Variants\n\
-             \n\
-             \n* `b(int)`\
-             \n\
-             \n* `c(int)` - a\n\n"));
-    }
-
-    #[test]
-    fn should_write_trait_header() {
-        let markdown = render(~"trait i { fn a(); }");
-        assert!(markdown.contains("## Trait `i`"));
-    }
-
-    #[test]
-    fn should_write_trait_desc() {
-        let markdown = render(~"#[doc = \"desc\"] trait i { fn a(); }");
-        assert!(markdown.contains("desc"));
-    }
-
-    #[test]
-    fn should_write_trait_method_header() {
-        let markdown = render(~"trait i { fn a(); }");
-        assert!(markdown.contains("### Method `a`"));
-    }
-
-    #[test]
-    fn should_write_trait_method_signature() {
-        let markdown = render(~"trait i { fn a(&self); }");
-        assert!(markdown.contains("\n~~~ {.rust}\nfn a(&self)"));
-    }
-
-    #[test]
-    fn should_write_impl_header() {
-        let markdown = render(~"impl int { fn a() { } }");
-        assert!(markdown.contains("## Implementation for `int`"));
-    }
-
-    #[test]
-    fn should_write_impl_header_with_bounds() {
-        let markdown = render(~"impl <T> int<T> { }");
-        assert!(markdown.contains("## Implementation for `int<T>` where `<T>`"));
-    }
-
-    #[test]
-    fn should_write_impl_header_with_trait() {
-        let markdown = render(~"impl j for int { fn a() { } }");
-        assert!(markdown.contains(
-                              "## Implementation of `j` for `int`"));
-    }
-
-    #[test]
-    fn should_write_impl_desc() {
-        let markdown = render(
-            ~"#[doc = \"desc\"] impl int { fn a() { } }");
-        assert!(markdown.contains("desc"));
-    }
-
-    #[test]
-    fn should_write_impl_method_header() {
-        let markdown = render(
-            ~"impl int { fn a() { } }");
-        assert!(markdown.contains("### Method `a`"));
-    }
-
-    #[test]
-    fn should_write_impl_method_signature() {
-        let markdown = render(
-            ~"impl int { fn a(&mut self) { } }");
-        assert!(markdown.contains("~~~ {.rust}\nfn a(&mut self)"));
-    }
-
-    #[test]
-    fn should_write_type_header() {
-        let markdown = render(~"type t = int;");
-        assert!(markdown.contains("## Type `t`"));
-    }
-
-    #[test]
-    fn should_write_type_desc() {
-        let markdown = render(
-            ~"#[doc = \"desc\"] type t = int;");
-        assert!(markdown.contains("\n\ndesc\n\n"));
-    }
-
-    #[test]
-    fn should_write_type_signature() {
-        let markdown = render(~"type t = int;");
-        assert!(markdown.contains("\n\n~~~ {.rust}\ntype t = int\n~~~\n"));
-    }
-
-    #[test]
-    fn should_put_struct_header() {
-        let markdown = render(~"struct S { field: () }");
-        assert!(markdown.contains("## Struct `S`\n\n"));
-    }
-}