diff options
Diffstat (limited to 'src/librustdoc/markdown_pass.rs')
| -rw-r--r-- | src/librustdoc/markdown_pass.rs | 918 |
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")); + } } |
