2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Generate markdown from a document tree
|
2012-01-17 19:44:32 -06:00
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use astsrv;
|
2012-12-29 19:38:20 -06:00
|
|
|
use attr_pass;
|
|
|
|
use config;
|
|
|
|
use desc_to_brief_pass;
|
2012-09-18 18:48:40 -05:00
|
|
|
use doc::ItemUtils;
|
2012-12-23 16:41:37 -06:00
|
|
|
use doc;
|
2012-12-29 19:38:20 -06:00
|
|
|
use extract;
|
2012-12-23 16:41:37 -06:00
|
|
|
use fold;
|
2012-12-29 19:38:20 -06:00
|
|
|
use markdown_index_pass;
|
2012-12-23 16:41:37 -06:00
|
|
|
use markdown_pass;
|
2012-09-18 18:48:40 -05:00
|
|
|
use markdown_writer::Writer;
|
|
|
|
use markdown_writer::WriterUtils;
|
|
|
|
use markdown_writer::WriterFactory;
|
2012-12-29 19:38:20 -06:00
|
|
|
use markdown_writer;
|
|
|
|
use page_pass;
|
2013-01-08 21:37:25 -06:00
|
|
|
use pass::Pass;
|
2012-12-29 19:38:20 -06:00
|
|
|
use path_pass;
|
|
|
|
use sectionalize_pass;
|
2012-12-23 16:41:37 -06:00
|
|
|
use sort_pass;
|
2012-12-29 19:38:20 -06:00
|
|
|
use trim_pass;
|
|
|
|
use unindent_pass;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2012-12-29 19:38:20 -06:00
|
|
|
use core::iter;
|
|
|
|
use core::oldcomm;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::str;
|
|
|
|
use core::vec;
|
|
|
|
use std::par;
|
|
|
|
use syntax;
|
2012-03-01 00:26:28 -06:00
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn mk_pass(writer_factory: WriterFactory) -> Pass {
|
2012-09-19 00:43:54 -05:00
|
|
|
let f = fn~(move writer_factory,
|
2013-01-30 21:32:36 -06:00
|
|
|
srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
|
2012-05-24 16:49:39 -05:00
|
|
|
run(srv, doc, copy writer_factory)
|
2012-02-27 20:07:16 -06:00
|
|
|
};
|
|
|
|
|
2013-01-08 16:00:45 -06:00
|
|
|
Pass {
|
2012-07-14 00:57:48 -05:00
|
|
|
name: ~"markdown",
|
2012-09-19 00:43:54 -05:00
|
|
|
f: move f
|
2012-01-29 16:51:09 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-29 20:10:40 -06:00
|
|
|
fn run(
|
2012-09-18 18:48:40 -05:00
|
|
|
srv: astsrv::Srv,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::Doc,
|
|
|
|
writer_factory: WriterFactory
|
2012-09-18 18:48:40 -05:00
|
|
|
) -> doc::Doc {
|
2012-02-29 20:10:40 -06:00
|
|
|
|
2012-09-18 18:48:40 -05:00
|
|
|
pure fn mods_last(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool {
|
|
|
|
pure fn is_mod(item: &doc::ItemTag) -> bool {
|
2012-08-06 14:34:08 -05:00
|
|
|
match *item {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ModTag(_) => true,
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => false
|
2012-02-29 20:10:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lteq = !is_mod(item1) || is_mod(item2);
|
|
|
|
lteq
|
|
|
|
}
|
|
|
|
|
2012-02-29 21:06:50 -06:00
|
|
|
// 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.
|
2012-11-29 19:51:16 -06:00
|
|
|
let sorted_doc = (sort_pass::mk_pass(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"mods last", mods_last
|
2013-01-30 15:14:35 -06:00
|
|
|
).f)(srv, copy doc);
|
2012-02-29 20:10:40 -06:00
|
|
|
|
2012-09-19 00:43:54 -05:00
|
|
|
write_markdown(sorted_doc, move writer_factory);
|
2012-02-29 21:06:50 -06:00
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return doc;
|
2012-02-29 20:10:40 -06:00
|
|
|
}
|
|
|
|
|
2012-01-29 16:51:09 -06:00
|
|
|
#[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(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"mod a { }\
|
2012-01-29 16:51:09 -06:00
|
|
|
fn b() { }\
|
2012-09-21 20:10:45 -05:00
|
|
|
mod c {
|
2013-01-30 16:10:03 -06:00
|
|
|
}\
|
2012-01-29 16:51:09 -06:00
|
|
|
fn d() { }"
|
|
|
|
);
|
|
|
|
|
2012-09-21 21:37:57 -05:00
|
|
|
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();
|
2012-01-29 16:51:09 -06:00
|
|
|
|
|
|
|
assert idx_b < idx_d;
|
|
|
|
assert idx_d < idx_a;
|
|
|
|
assert idx_a < idx_c;
|
2012-01-17 18:12:50 -06:00
|
|
|
}
|
2012-01-16 15:23:42 -06:00
|
|
|
|
2013-01-30 21:45:39 -06:00
|
|
|
struct Ctxt {
|
2012-09-18 18:48:40 -05:00
|
|
|
w: Writer
|
2013-01-30 21:45:39 -06:00
|
|
|
}
|
2012-01-16 00:58:57 -06:00
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
pub fn write_markdown(
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::Doc,
|
|
|
|
writer_factory: WriterFactory
|
2012-01-16 02:33:36 -06:00
|
|
|
) {
|
2012-10-11 18:42:40 -05:00
|
|
|
// There is easy parallelism to be had here, but
|
|
|
|
// we don't want to spawn too many pandoc processes.
|
|
|
|
// (See #2484, which is closed.)
|
2012-08-14 16:36:28 -05:00
|
|
|
do doc.pages.map |page| {
|
2013-01-30 21:45:39 -06:00
|
|
|
let ctxt = Ctxt {
|
2013-01-30 15:14:35 -06:00
|
|
|
w: writer_factory(copy *page)
|
2012-03-06 16:07:34 -06:00
|
|
|
};
|
2012-11-21 00:36:32 -06:00
|
|
|
write_page(&ctxt, page)
|
2012-03-06 17:01:40 -06:00
|
|
|
};
|
2012-03-06 16:07:34 -06:00
|
|
|
}
|
2012-01-16 02:33:36 -06:00
|
|
|
|
2012-11-21 00:36:32 -06:00
|
|
|
fn write_page(ctxt: &Ctxt, page: &doc::Page) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_title(ctxt, copy *page);
|
|
|
|
match copy *page {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::CratePage(doc) => {
|
2012-03-06 16:07:34 -06:00
|
|
|
write_crate(ctxt, doc);
|
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ItemPage(doc) => {
|
2012-03-10 18:21:23 -06:00
|
|
|
// 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);
|
2012-03-06 16:07:34 -06:00
|
|
|
}
|
|
|
|
}
|
2012-02-29 21:06:50 -06:00
|
|
|
ctxt.w.write_done();
|
2012-01-16 23:37:29 -06:00
|
|
|
}
|
|
|
|
|
2012-03-06 16:07:34 -06:00
|
|
|
#[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();
|
2012-07-14 00:57:48 -05:00
|
|
|
let (srv, doc) = test::create_doc_srv(~"mod a { }");
|
2012-03-06 16:07:34 -06:00
|
|
|
// Split the document up into pages
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
|
2012-09-19 00:43:54 -05:00
|
|
|
write_markdown(doc, move writer_factory);
|
2012-03-06 16:07:34 -06:00
|
|
|
// We expect two pages to have been written
|
2012-09-19 00:43:54 -05:00
|
|
|
for iter::repeat(2) {
|
2012-12-13 16:18:47 -06:00
|
|
|
oldcomm::recv(po);
|
2012-03-06 16:07:34 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_title(ctxt: &Ctxt, page: doc::Page) {
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("%% %s", make_title(page)));
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn make_title(page: doc::Page) -> ~str {
|
2012-08-06 14:34:08 -05:00
|
|
|
let item = match page {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::CratePage(CrateDoc) => {
|
2013-01-30 15:14:35 -06:00
|
|
|
doc::ModTag(copy CrateDoc.topmod)
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ItemPage(ItemTag) => {
|
|
|
|
ItemTag
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
let title = markdown_pass::header_text(item);
|
2012-07-14 00:57:48 -05:00
|
|
|
let title = str::replace(title, ~"`", ~"");
|
2012-08-01 19:30:05 -05:00
|
|
|
return title;
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_title_for_each_page() {
|
|
|
|
let (writer_factory, po) = markdown_writer::future_writer_factory();
|
|
|
|
let (srv, doc) = test::create_doc_srv(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"#[link(name = \"core\")]; mod a { }");
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
|
2012-09-19 00:43:54 -05:00
|
|
|
write_markdown(doc, move writer_factory);
|
|
|
|
for iter::repeat(2) {
|
2012-12-13 16:18:47 -06:00
|
|
|
let (page, markdown) = oldcomm::recv(po);
|
2012-08-06 14:34:08 -05:00
|
|
|
match page {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::CratePage(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"% Crate core");
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ItemPage(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"% Module a");
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 18:48:40 -05:00
|
|
|
enum Hlvl {
|
|
|
|
H1 = 1,
|
|
|
|
H2 = 2,
|
|
|
|
H3 = 3,
|
|
|
|
H4 = 4
|
2012-01-16 02:59:18 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_header(ctxt: &Ctxt, lvl: Hlvl, doc: doc::ItemTag) {
|
2012-03-01 20:13:22 -06:00
|
|
|
let text = header_text(doc);
|
|
|
|
write_header_(ctxt, lvl, text);
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_header_(ctxt: &Ctxt, lvl: Hlvl, title: ~str) {
|
2012-03-12 17:52:30 -05:00
|
|
|
let hashes = str::from_chars(vec::from_elem(lvl as uint, '#'));
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("%s %s", hashes, title));
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-01-17 00:01:25 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn header_kind(doc: doc::ItemTag) -> ~str {
|
2012-08-06 14:34:08 -05:00
|
|
|
match doc {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ModTag(_) => {
|
2012-05-13 19:12:56 -05:00
|
|
|
if doc.id() == syntax::ast::crate_node_id {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Crate"
|
2012-03-01 20:13:22 -06:00
|
|
|
} else {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Module"
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::NmodTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Foreign module"
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::FnTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Function"
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ConstTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Const"
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::EnumTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Enum"
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::TraitTag(_) => {
|
2013-01-03 13:34:08 -06:00
|
|
|
~"Trait"
|
2012-03-02 17:17:13 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ImplTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Implementation"
|
2012-03-02 17:17:13 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::TyTag(_) => {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"Type"
|
2012-03-02 17:17:13 -06:00
|
|
|
}
|
2012-09-19 16:37:43 -05:00
|
|
|
doc::StructTag(_) => {
|
|
|
|
~"Struct"
|
|
|
|
}
|
2012-03-02 17:17:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn header_name(doc: doc::ItemTag) -> ~str {
|
2012-07-14 00:57:48 -05:00
|
|
|
let fullpath = str::connect(doc.path() + ~[doc.name()], ~"::");
|
2013-01-30 15:14:35 -06:00
|
|
|
match &doc {
|
|
|
|
&doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => {
|
2012-03-02 17:17:13 -06:00
|
|
|
fullpath
|
|
|
|
}
|
2013-01-30 15:14:35 -06:00
|
|
|
&doc::NmodTag(_) => {
|
2012-03-02 17:17:13 -06:00
|
|
|
fullpath
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2013-01-30 15:14:35 -06:00
|
|
|
&doc::ImplTag(ref doc) => {
|
2012-09-21 21:37:57 -05:00
|
|
|
assert doc.self_ty.is_some();
|
2013-01-30 15:14:35 -06:00
|
|
|
let self_ty = (&doc.self_ty).get();
|
2012-07-18 11:31:53 -05:00
|
|
|
let mut trait_part = ~"";
|
|
|
|
for doc.trait_types.eachi |i, trait_type| {
|
|
|
|
if i == 0 {
|
|
|
|
trait_part += ~" of ";
|
|
|
|
} else {
|
2012-08-03 13:22:35 -05:00
|
|
|
trait_part += ~", ";
|
2012-07-18 11:31:53 -05:00
|
|
|
}
|
2012-09-21 20:43:30 -05:00
|
|
|
trait_part += *trait_type;
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-09-19 18:09:43 -05:00
|
|
|
fmt!("%s for %s", trait_part, self_ty)
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-03-02 17:17:13 -06:00
|
|
|
doc.name()
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn header_text(doc: doc::ItemTag) -> ~str {
|
2013-01-30 15:14:35 -06:00
|
|
|
match &doc {
|
|
|
|
&doc::ImplTag(ref ImplDoc) => {
|
|
|
|
let header_kind = header_kind(copy doc);
|
2012-09-18 18:48:40 -05:00
|
|
|
let desc = if ImplDoc.trait_types.is_empty() {
|
2013-01-30 15:14:35 -06:00
|
|
|
fmt!("for `%s`", (&ImplDoc.self_ty).get())
|
2012-08-08 19:19:06 -05:00
|
|
|
} else {
|
2012-09-18 18:48:40 -05:00
|
|
|
fmt!("of `%s` for `%s`", ImplDoc.trait_types[0],
|
2013-01-30 15:14:35 -06:00
|
|
|
(&ImplDoc.self_ty).get())
|
2012-08-08 19:19:06 -05:00
|
|
|
};
|
2013-01-10 12:59:58 -06:00
|
|
|
return fmt!("%s %s", header_kind, desc);
|
2012-08-08 19:19:06 -05:00
|
|
|
}
|
2013-01-10 12:59:58 -06:00
|
|
|
_ => {}
|
2012-08-08 19:19:06 -05:00
|
|
|
}
|
2013-01-10 12:59:58 -06:00
|
|
|
|
|
|
|
header_text_(header_kind(copy doc),
|
|
|
|
header_name(doc))
|
2012-03-02 17:17:13 -06:00
|
|
|
}
|
|
|
|
|
2012-11-21 00:36:32 -06:00
|
|
|
fn header_text_(kind: &str, name: &str) -> ~str {
|
2012-08-22 19:24:52 -05:00
|
|
|
fmt!("%s `%s`", kind, name)
|
2012-03-01 20:13:22 -06:00
|
|
|
}
|
|
|
|
|
2012-01-16 23:37:29 -06:00
|
|
|
fn write_crate(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::CrateDoc
|
2012-01-16 23:37:29 -06:00
|
|
|
) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_top_module(ctxt, copy doc.topmod);
|
2012-01-16 17:44:10 -06:00
|
|
|
}
|
|
|
|
|
2012-01-16 02:59:18 -06:00
|
|
|
fn write_top_module(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
ModDoc: doc::ModDoc
|
2012-01-16 02:59:18 -06:00
|
|
|
) {
|
2012-09-18 18:48:40 -05:00
|
|
|
write_mod_contents(ctxt, ModDoc);
|
2012-01-16 02:59:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn write_mod(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
ModDoc: doc::ModDoc
|
2012-01-16 02:59:18 -06:00
|
|
|
) {
|
2012-09-18 18:48:40 -05:00
|
|
|
write_mod_contents(ctxt, ModDoc);
|
2012-01-16 02:59:18 -06:00
|
|
|
}
|
|
|
|
|
2012-01-19 02:03:45 -06:00
|
|
|
#[test]
|
|
|
|
fn should_write_full_path_to_mod() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"mod a { mod b { mod c { } } }");
|
|
|
|
assert str::contains(markdown, ~"# Module `a::b::c`");
|
2012-01-19 02:03:45 -06:00
|
|
|
}
|
|
|
|
|
2012-12-13 16:18:47 -06:00
|
|
|
fn write_oldcommon(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
desc: Option<~str>,
|
2012-11-21 00:36:32 -06:00
|
|
|
sections: &[doc::Section]
|
2012-03-09 18:37:19 -06:00
|
|
|
) {
|
|
|
|
write_desc(ctxt, desc);
|
|
|
|
write_sections(ctxt, sections);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_desc(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
desc: Option<~str>
|
2012-03-09 18:37:19 -06:00
|
|
|
) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match desc {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(desc) => {
|
2012-03-09 18:37:19 -06:00
|
|
|
ctxt.w.write_line(desc);
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-03-09 18:37:19 -06:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => ()
|
2012-03-09 18:37:19 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-21 00:36:32 -06:00
|
|
|
fn write_sections(ctxt: &Ctxt, sections: &[doc::Section]) {
|
2012-09-18 23:41:37 -05:00
|
|
|
for vec::each(sections) |section| {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_section(ctxt, copy *section);
|
2012-03-09 18:37:19 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_section(ctxt: &Ctxt, section: doc::Section) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_header_(ctxt, H4, copy section.header);
|
|
|
|
ctxt.w.write_line(copy section.body);
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-03-09 18:37:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_sections() {
|
|
|
|
let markdown = test::render(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"#[doc = \"\
|
2012-03-09 18:37:19 -06:00
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
2012-09-21 20:10:45 -05:00
|
|
|
mod a {
|
2013-01-30 16:10:03 -06:00
|
|
|
}");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"#### Header\n\nBody\n\n");
|
2012-03-09 18:37:19 -06:00
|
|
|
}
|
|
|
|
|
2012-01-16 02:59:18 -06:00
|
|
|
fn write_mod_contents(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::ModDoc
|
2012-01-16 02:59:18 -06:00
|
|
|
) {
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-09-21 21:37:57 -05:00
|
|
|
if doc.index.is_some() {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_index(ctxt, (&doc.index).get());
|
2012-03-02 18:20:36 -06:00
|
|
|
}
|
2012-01-18 23:33:37 -06:00
|
|
|
|
2012-09-19 18:55:01 -05:00
|
|
|
for doc.items.each |itemTag| {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_item(ctxt, copy *itemTag);
|
2012-03-06 16:07:34 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_item(ctxt: &Ctxt, doc: doc::ItemTag) {
|
2012-03-10 18:21:23 -06:00
|
|
|
write_item_(ctxt, doc, true);
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_item_no_header(ctxt: &Ctxt, doc: doc::ItemTag) {
|
2012-03-10 18:21:23 -06:00
|
|
|
write_item_(ctxt, doc, false);
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) {
|
2012-03-10 18:21:23 -06:00
|
|
|
if write_header {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_item_header(ctxt, copy doc);
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match doc {
|
2012-09-18 18:48:40 -05:00
|
|
|
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),
|
2012-09-19 16:37:43 -05:00
|
|
|
doc::TyTag(TyDoc) => write_type(ctxt, TyDoc),
|
|
|
|
doc::StructTag(StructDoc) => write_struct(ctxt, StructDoc),
|
2012-01-28 16:36:35 -06:00
|
|
|
}
|
2012-01-16 02:59:18 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_item_header(ctxt: &Ctxt, doc: doc::ItemTag) {
|
|
|
|
write_header(ctxt, item_header_lvl(&doc), doc);
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl {
|
2012-08-06 14:34:08 -05:00
|
|
|
match doc {
|
2013-01-30 21:32:36 -06:00
|
|
|
&doc::ModTag(_) | &doc::NmodTag(_) => H1,
|
2012-09-18 18:48:40 -05:00
|
|
|
_ => H2
|
2012-03-10 18:21:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-18 23:33:37 -06:00
|
|
|
#[test]
|
|
|
|
fn should_write_crate_description() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"#[doc = \"this is the crate\"];");
|
|
|
|
assert str::contains(markdown, ~"this is the crate");
|
2012-01-18 23:33:37 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_index(ctxt: &Ctxt, index: doc::Index) {
|
2012-03-02 18:20:36 -06:00
|
|
|
if vec::is_empty(index.entries) {
|
2012-08-01 19:30:05 -05:00
|
|
|
return;
|
2012-03-02 18:20:36 -06:00
|
|
|
}
|
2012-03-02 18:27:31 -06:00
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
for index.entries.each |entry| {
|
2012-03-02 18:20:36 -06:00
|
|
|
let header = header_text_(entry.kind, entry.name);
|
2013-01-30 15:14:35 -06:00
|
|
|
let id = copy entry.link;
|
2012-09-21 21:37:57 -05:00
|
|
|
if entry.brief.is_some() {
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("* [%s](%s) - %s",
|
2013-01-30 15:14:35 -06:00
|
|
|
header, id, (&entry.brief).get()));
|
2012-03-06 18:51:40 -06:00
|
|
|
} else {
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("* [%s](%s)", header, id));
|
2012-03-06 18:51:40 -06:00
|
|
|
}
|
2012-03-02 18:20:36 -06:00
|
|
|
}
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-03-02 18:20:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_index() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"mod a { } mod b { }");
|
2012-03-02 18:20:36 -06:00
|
|
|
assert str::contains(
|
|
|
|
markdown,
|
2012-07-14 00:57:48 -05:00
|
|
|
~"\n\n* [Module `a`](#module-a)\n\
|
2012-06-28 12:42:19 -05:00
|
|
|
* [Module `b`](#module-b)\n\n"
|
2012-03-02 18:20:36 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-03-06 18:51:40 -06:00
|
|
|
#[test]
|
|
|
|
fn should_write_index_brief() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"#[doc = \"test\"] mod a { }");
|
|
|
|
assert str::contains(markdown, ~"(#module-a) - test\n");
|
2012-03-06 18:51:40 -06:00
|
|
|
}
|
|
|
|
|
2012-03-02 18:20:36 -06:00
|
|
|
#[test]
|
|
|
|
fn should_not_write_index_if_no_entries() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"");
|
|
|
|
assert !str::contains(markdown, ~"\n\n\n");
|
2012-03-02 18:20:36 -06:00
|
|
|
}
|
|
|
|
|
2012-03-11 18:36:20 -05:00
|
|
|
#[test]
|
2012-06-26 18:18:37 -05:00
|
|
|
fn should_write_index_for_foreign_mods() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"extern mod a { fn a(); }");
|
2012-03-11 18:36:20 -05:00
|
|
|
assert str::contains(
|
|
|
|
markdown,
|
2012-07-14 00:57:48 -05:00
|
|
|
~"\n\n* [Function `a`](#function-a)\n\n"
|
2012-03-11 18:36:20 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) {
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-09-21 21:37:57 -05:00
|
|
|
if doc.index.is_some() {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_index(ctxt, (&doc.index).get());
|
2012-03-11 18:36:20 -05:00
|
|
|
}
|
2012-02-24 17:07:08 -06:00
|
|
|
|
2012-09-18 18:48:40 -05:00
|
|
|
for doc.fns.each |FnDoc| {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_item_header(ctxt, doc::FnTag(copy *FnDoc));
|
|
|
|
write_fn(ctxt, copy *FnDoc);
|
2012-02-24 17:07:08 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-06-26 18:18:37 -05:00
|
|
|
fn should_write_foreign_mods() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"#[doc = \"test\"] extern mod a { }");
|
|
|
|
assert str::contains(markdown, ~"Foreign module `a`");
|
|
|
|
assert str::contains(markdown, ~"test");
|
2012-02-24 17:07:08 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-06-26 18:18:37 -05:00
|
|
|
fn should_write_foreign_fns() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(
|
|
|
|
~"extern mod a { #[doc = \"test\"] fn a(); }");
|
|
|
|
assert str::contains(markdown, ~"test");
|
2012-02-24 17:07:08 -06:00
|
|
|
}
|
|
|
|
|
2012-03-10 18:43:38 -06:00
|
|
|
#[test]
|
2012-06-26 18:18:37 -05:00
|
|
|
fn should_write_foreign_fn_headers() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(
|
|
|
|
~"extern mod a { #[doc = \"test\"] fn a(); }");
|
|
|
|
assert str::contains(markdown, ~"## Function `a`");
|
2012-03-10 18:43:38 -06:00
|
|
|
}
|
|
|
|
|
2012-01-16 02:59:18 -06:00
|
|
|
fn write_fn(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::FnDoc
|
2012-01-16 02:59:18 -06:00
|
|
|
) {
|
2012-01-30 22:53:52 -06:00
|
|
|
write_fnlike(
|
|
|
|
ctxt,
|
2013-01-30 15:14:35 -06:00
|
|
|
copy doc.sig,
|
2012-02-17 16:46:30 -06:00
|
|
|
doc.desc(),
|
2012-03-09 19:23:56 -06:00
|
|
|
doc.sections()
|
2012-01-30 22:53:52 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_fnlike(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
sig: Option<~str>,
|
|
|
|
desc: Option<~str>,
|
2012-11-21 00:36:32 -06:00
|
|
|
sections: &[doc::Section]
|
2012-01-30 22:53:52 -06:00
|
|
|
) {
|
|
|
|
write_sig(ctxt, sig);
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, desc, sections);
|
2012-01-18 01:39:22 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_sig(ctxt: &Ctxt, sig: Option<~str>) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match sig {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(sig) => {
|
2012-01-23 19:58:40 -06:00
|
|
|
ctxt.w.write_line(code_block_indent(sig));
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-01-19 20:58:44 -06:00
|
|
|
}
|
2013-01-31 19:51:01 -06:00
|
|
|
None => die!(~"unimplemented")
|
2012-01-19 20:58:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn code_block_indent(s: ~str) -> ~str {
|
2012-01-23 19:58:40 -06:00
|
|
|
let lines = str::lines_any(s);
|
2012-09-21 20:43:30 -05:00
|
|
|
let indented = vec::map(lines, |line| fmt!(" %s", *line) );
|
2012-07-14 00:57:48 -05:00
|
|
|
str::connect(indented, ~"\n")
|
2012-01-23 19:58:40 -06:00
|
|
|
}
|
|
|
|
|
2012-01-27 00:45:37 -06:00
|
|
|
#[test]
|
|
|
|
fn write_markdown_should_write_function_header() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"fn func() { }");
|
|
|
|
assert str::contains(markdown, ~"## Function `func`");
|
2012-01-27 00:45:37 -06:00
|
|
|
}
|
|
|
|
|
2012-01-19 20:58:44 -06:00
|
|
|
#[test]
|
|
|
|
fn should_write_the_function_signature() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"#[doc = \"f\"] fn a() { }");
|
|
|
|
assert str::contains(markdown, ~"\n fn a()\n");
|
2012-01-19 20:58:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_insert_blank_line_after_fn_signature() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"#[doc = \"f\"] fn a() { }");
|
|
|
|
assert str::contains(markdown, ~"fn a()\n\n");
|
2012-01-19 20:58:44 -06:00
|
|
|
}
|
|
|
|
|
2012-01-23 19:58:40 -06:00
|
|
|
#[test]
|
|
|
|
fn should_correctly_indent_fn_signature() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let doc = test::create_doc(~"fn a() { }");
|
2013-01-29 21:45:53 -06:00
|
|
|
let doc = doc::Doc{
|
2012-06-29 18:26:56 -05:00
|
|
|
pages: ~[
|
2013-01-29 21:45:53 -06:00
|
|
|
doc::CratePage(doc::CrateDoc{
|
|
|
|
topmod: doc::ModDoc{
|
|
|
|
items: ~[doc::FnTag(doc::SimpleItemDoc{
|
2012-09-04 15:29:32 -05:00
|
|
|
sig: Some(~"line 1\nline 2"),
|
2013-01-30 15:14:35 -06:00
|
|
|
.. copy doc.cratemod().fns()[0]
|
2012-09-04 15:29:32 -05:00
|
|
|
})],
|
2013-01-29 21:45:53 -06:00
|
|
|
.. doc.cratemod()
|
|
|
|
},
|
2012-09-18 18:48:40 -05:00
|
|
|
.. doc.CrateDoc()
|
2012-03-02 20:33:25 -06:00
|
|
|
})
|
2012-06-29 18:26:56 -05:00
|
|
|
]
|
2013-01-29 21:45:53 -06:00
|
|
|
};
|
2012-01-23 19:58:40 -06:00
|
|
|
let markdown = test::write_markdown_str(doc);
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~" line 1\n line 2");
|
2012-01-23 19:58:40 -06:00
|
|
|
}
|
|
|
|
|
2012-01-27 00:45:37 -06:00
|
|
|
#[test]
|
|
|
|
fn should_leave_blank_line_between_fn_header_and_sig() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"fn a() { }");
|
|
|
|
assert str::contains(markdown, ~"Function `a`\n\n fn a()");
|
2012-01-27 00:45:37 -06:00
|
|
|
}
|
|
|
|
|
2012-01-24 02:51:19 -06:00
|
|
|
fn write_const(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::ConstDoc
|
2012-01-24 02:51:19 -06:00
|
|
|
) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_sig(ctxt, copy doc.sig);
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-01-24 02:51:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_const_header() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"const a: bool = true;");
|
|
|
|
assert str::contains(markdown, ~"## Const `a`\n\n");
|
2012-01-24 02:51:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_const_description() {
|
|
|
|
let markdown = test::render(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"#[doc = \"b\"]\
|
2012-01-24 02:51:19 -06:00
|
|
|
const a: bool = true;");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"\n\nb\n\n");
|
2012-01-24 02:51:19 -06:00
|
|
|
}
|
|
|
|
|
2012-01-25 22:55:55 -06:00
|
|
|
fn write_enum(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::EnumDoc
|
2012-01-25 22:55:55 -06:00
|
|
|
) {
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-01-25 22:55:55 -06:00
|
|
|
write_variants(ctxt, doc.variants);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_enum_header() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"enum a { b }");
|
|
|
|
assert str::contains(markdown, ~"## Enum `a`\n\n");
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_enum_description() {
|
|
|
|
let markdown = test::render(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"#[doc = \"b\"] enum a { b }");
|
|
|
|
assert str::contains(markdown, ~"\n\nb\n\n");
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn write_variants(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
|
|
|
docs: &[doc::VariantDoc]
|
2012-01-25 22:55:55 -06:00
|
|
|
) {
|
|
|
|
if vec::is_empty(docs) {
|
2012-08-01 19:30:05 -05:00
|
|
|
return;
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
|
|
|
|
2012-09-18 18:48:40 -05:00
|
|
|
write_header_(ctxt, H4, ~"Variants");
|
2012-01-25 22:55:55 -06:00
|
|
|
|
2012-09-18 23:41:37 -05:00
|
|
|
for vec::each(docs) |variant| {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_variant(ctxt, copy *variant);
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-01-25 22:55:55 -06:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
ctxt.w.write_line(~"");
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) {
|
2012-09-21 21:37:57 -05:00
|
|
|
assert doc.sig.is_some();
|
2013-01-30 15:14:35 -06:00
|
|
|
let sig = (&doc.sig).get();
|
|
|
|
match copy doc.desc {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(desc) => {
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("* `%s` - %s", sig, desc));
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-08-22 19:24:52 -05:00
|
|
|
ctxt.w.write_line(fmt!("* `%s`", sig));
|
2012-01-25 22:55:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_variant_list() {
|
|
|
|
let markdown = test::render(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"enum a { \
|
2012-01-25 22:55:55 -06:00
|
|
|
#[doc = \"test\"] b, \
|
|
|
|
#[doc = \"test\"] c }");
|
|
|
|
assert str::contains(
|
|
|
|
markdown,
|
2012-07-14 00:57:48 -05:00
|
|
|
~"\n\n#### Variants\n\
|
2012-01-25 22:55:55 -06:00
|
|
|
\n* `b` - test\
|
|
|
|
\n* `c` - test\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_variant_list_without_descs() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"enum a { b, c }");
|
2012-01-25 22:55:55 -06:00
|
|
|
assert str::contains(
|
|
|
|
markdown,
|
2012-07-14 00:57:48 -05:00
|
|
|
~"\n\n#### Variants\n\
|
2012-01-25 22:55:55 -06:00
|
|
|
\n* `b`\
|
|
|
|
\n* `c`\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_variant_list_with_signatures() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"enum a { b(int), #[doc = \"a\"] c(int) }");
|
2012-01-25 22:55:55 -06:00
|
|
|
assert str::contains(
|
|
|
|
markdown,
|
2012-07-14 00:57:48 -05:00
|
|
|
~"\n\n#### Variants\n\
|
2012-01-25 22:55:55 -06:00
|
|
|
\n* `b(int)`\
|
|
|
|
\n* `c(int)` - a\n\n");
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) {
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-01-30 22:53:52 -06:00
|
|
|
write_methods(ctxt, doc.methods);
|
|
|
|
}
|
|
|
|
|
2012-11-21 00:36:32 -06:00
|
|
|
fn write_methods(ctxt: &Ctxt, docs: &[doc::MethodDoc]) {
|
2012-09-18 23:41:37 -05:00
|
|
|
for vec::each(docs) |doc| {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_method(ctxt, copy *doc);
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-01-30 22:53:52 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) {
|
2012-09-18 18:48:40 -05:00
|
|
|
write_header_(ctxt, H3, header_text_(~"Method", doc.name));
|
2012-01-30 22:53:52 -06:00
|
|
|
write_fnlike(
|
|
|
|
ctxt,
|
2013-01-30 15:14:35 -06:00
|
|
|
copy doc.sig,
|
|
|
|
copy doc.desc,
|
2012-03-09 19:23:56 -06:00
|
|
|
doc.sections
|
2012-01-30 22:53:52 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 18:30:42 -05:00
|
|
|
fn should_write_trait_header() {
|
2012-07-31 12:27:51 -05:00
|
|
|
let markdown = test::render(~"trait i { fn a(); }");
|
2013-01-03 13:34:08 -06:00
|
|
|
assert str::contains(markdown, ~"## Trait `i`");
|
2012-01-30 22:53:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 18:30:42 -05:00
|
|
|
fn should_write_trait_desc() {
|
2012-01-30 22:53:52 -06:00
|
|
|
let markdown = test::render(
|
2012-07-31 12:27:51 -05:00
|
|
|
~"#[doc = \"desc\"] trait i { fn a(); }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"desc");
|
2012-01-30 22:53:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 18:30:42 -05:00
|
|
|
fn should_write_trait_method_header() {
|
2012-01-30 22:53:52 -06:00
|
|
|
let markdown = test::render(
|
2012-07-31 12:27:51 -05:00
|
|
|
~"trait i { fn a(); }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"### Method `a`");
|
2012-01-30 22:53:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 18:30:42 -05:00
|
|
|
fn should_write_trait_method_signature() {
|
2012-01-30 22:53:52 -06:00
|
|
|
let markdown = test::render(
|
2012-07-31 12:27:51 -05:00
|
|
|
~"trait i { fn a(); }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"\n fn a()");
|
2012-01-30 22:53:52 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) {
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-01-31 22:54:46 -06:00
|
|
|
write_methods(ctxt, doc.methods);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_impl_header() {
|
2012-08-08 19:19:06 -05:00
|
|
|
let markdown = test::render(~"impl int { fn a() { } }");
|
|
|
|
assert str::contains(markdown, ~"## Implementation for `int`");
|
2012-01-31 22:54:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 18:30:42 -05:00
|
|
|
fn should_write_impl_header_with_trait() {
|
2012-08-08 19:19:06 -05:00
|
|
|
let markdown = test::render(~"impl int: j { fn a() { } }");
|
|
|
|
assert str::contains(markdown, ~"## Implementation of `j` for `int`");
|
2012-01-31 22:54:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_impl_desc() {
|
|
|
|
let markdown = test::render(
|
2012-08-08 19:19:06 -05:00
|
|
|
~"#[doc = \"desc\"] impl int { fn a() { } }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"desc");
|
2012-01-31 22:54:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_impl_method_header() {
|
|
|
|
let markdown = test::render(
|
2012-08-08 19:19:06 -05:00
|
|
|
~"impl int { fn a() { } }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"### Method `a`");
|
2012-01-31 22:54:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_impl_method_signature() {
|
|
|
|
let markdown = test::render(
|
2012-08-08 19:19:06 -05:00
|
|
|
~"impl int { fn a() { } }");
|
2012-07-14 00:57:48 -05:00
|
|
|
assert str::contains(markdown, ~"\n fn a()");
|
2012-01-31 22:54:46 -06:00
|
|
|
}
|
|
|
|
|
2012-02-02 00:41:41 -06:00
|
|
|
fn write_type(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::TyDoc
|
2012-02-02 00:41:41 -06:00
|
|
|
) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_sig(ctxt, copy doc.sig);
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-02-02 00:41:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_type_header() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"type t = int;");
|
|
|
|
assert str::contains(markdown, ~"## Type `t`");
|
2012-02-02 00:41:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_type_desc() {
|
|
|
|
let markdown = test::render(
|
2012-07-14 00:57:48 -05:00
|
|
|
~"#[doc = \"desc\"] type t = int;");
|
|
|
|
assert str::contains(markdown, ~"\n\ndesc\n\n");
|
2012-02-02 00:41:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_type_signature() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = test::render(~"type t = int;");
|
|
|
|
assert str::contains(markdown, ~"\n\n type t = int\n\n");
|
2012-02-02 00:41:41 -06:00
|
|
|
}
|
|
|
|
|
2012-09-19 16:37:43 -05:00
|
|
|
fn write_struct(
|
2012-11-21 00:36:32 -06:00
|
|
|
ctxt: &Ctxt,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::StructDoc
|
2012-09-19 16:37:43 -05:00
|
|
|
) {
|
2013-01-30 15:14:35 -06:00
|
|
|
write_sig(ctxt, copy doc.sig);
|
2012-12-13 16:18:47 -06:00
|
|
|
write_oldcommon(ctxt, doc.desc(), doc.sections());
|
2012-09-19 16:37:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_write_struct_header() {
|
|
|
|
let markdown = test::render(~"struct S { field: () }");
|
|
|
|
assert str::contains(markdown, ~"## Struct `S`\n\n");
|
|
|
|
}
|
|
|
|
|
2012-01-16 02:33:36 -06:00
|
|
|
#[cfg(test)]
|
2012-01-18 17:02:23 -06:00
|
|
|
mod test {
|
2012-12-29 19:38:20 -06:00
|
|
|
use astsrv;
|
|
|
|
use attr_pass;
|
|
|
|
use config;
|
|
|
|
use desc_to_brief_pass;
|
|
|
|
use doc;
|
|
|
|
use extract;
|
|
|
|
use markdown_index_pass;
|
2013-01-08 21:37:25 -06:00
|
|
|
use markdown_pass::{mk_pass, write_markdown};
|
2012-12-29 19:38:20 -06:00
|
|
|
use markdown_writer;
|
|
|
|
use path_pass;
|
|
|
|
use sectionalize_pass;
|
|
|
|
use trim_pass;
|
|
|
|
use tystr_pass;
|
|
|
|
use unindent_pass;
|
|
|
|
|
|
|
|
use core::oldcomm;
|
2013-01-08 21:37:25 -06:00
|
|
|
use core::path::Path;
|
2012-12-29 19:38:20 -06:00
|
|
|
use core::str;
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn render(source: ~str) -> ~str {
|
2012-01-29 16:51:09 -06:00
|
|
|
let (srv, doc) = create_doc_srv(source);
|
|
|
|
let markdown = write_markdown_str_srv(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("markdown: %s", markdown);
|
2012-01-23 19:58:40 -06:00
|
|
|
markdown
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) {
|
2012-06-30 18:19:07 -05:00
|
|
|
do astsrv::from_str(source) |srv| {
|
2012-03-06 17:57:36 -06:00
|
|
|
|
2013-01-29 21:45:53 -06:00
|
|
|
let config = config::Config {
|
2012-09-18 18:48:40 -05:00
|
|
|
output_style: config::DocPerCrate,
|
2012-09-04 15:29:32 -05:00
|
|
|
.. config::default_config(&Path("whatever"))
|
2012-03-06 17:57:36 -06:00
|
|
|
};
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
let doc = extract::from_srv(srv, ~"");
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (extract): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (tystr_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (tystr): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (path_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (path): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (attr_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (attr): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (desc_to_brief_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (desc_to_brief): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (unindent_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (unindent): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (sectionalize_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (trim): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (trim_pass::mk_pass().f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (sectionalize): %?", doc);
|
2012-12-03 19:08:52 -06:00
|
|
|
let doc = (markdown_index_pass::mk_pass(config).f)(srv, doc);
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("doc (index): %?", doc);
|
2012-02-20 23:08:19 -06:00
|
|
|
(srv, doc)
|
|
|
|
}
|
2012-01-29 16:51:09 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn create_doc(source: ~str) -> doc::Doc {
|
2012-01-29 16:51:09 -06:00
|
|
|
let (_, doc) = create_doc_srv(source);
|
2012-01-23 19:58:40 -06:00
|
|
|
doc
|
2012-01-18 01:33:11 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 16:10:03 -06:00
|
|
|
pub fn write_markdown_str(
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::Doc
|
2012-07-14 00:57:48 -05:00
|
|
|
) -> ~str {
|
2012-03-04 01:56:38 -06:00
|
|
|
let (writer_factory, po) = markdown_writer::future_writer_factory();
|
2012-09-19 00:43:54 -05:00
|
|
|
write_markdown(doc, move writer_factory);
|
2012-12-13 16:18:47 -06:00
|
|
|
return oldcomm::recv(po).second();
|
2012-01-16 02:33:36 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 16:10:03 -06:00
|
|
|
pub fn write_markdown_str_srv(
|
2012-09-18 18:48:40 -05:00
|
|
|
srv: astsrv::Srv,
|
2013-01-30 21:32:36 -06:00
|
|
|
doc: doc::Doc
|
2012-07-14 00:57:48 -05:00
|
|
|
) -> ~str {
|
2012-03-04 01:56:38 -06:00
|
|
|
let (writer_factory, po) = markdown_writer::future_writer_factory();
|
2012-09-19 00:43:54 -05:00
|
|
|
let pass = mk_pass(move writer_factory);
|
2012-12-03 19:08:52 -06:00
|
|
|
(pass.f)(srv, doc);
|
2012-12-13 16:18:47 -06:00
|
|
|
return oldcomm::recv(po).second();
|
2012-01-29 16:51:09 -06:00
|
|
|
}
|
|
|
|
|
2012-01-17 01:10:25 -06:00
|
|
|
#[test]
|
2013-01-30 16:10:03 -06:00
|
|
|
pub fn write_markdown_should_write_mod_headers() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = render(~"mod moo { }");
|
|
|
|
assert str::contains(markdown, ~"# Module `moo`");
|
2012-01-17 01:10:25 -06:00
|
|
|
}
|
2012-01-17 18:30:53 -06:00
|
|
|
|
|
|
|
#[test]
|
2013-01-30 16:10:03 -06:00
|
|
|
pub fn should_leave_blank_line_after_header() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let markdown = render(~"mod morp { }");
|
|
|
|
assert str::contains(markdown, ~"Module `morp`\n\n");
|
2012-01-18 01:29:23 -06:00
|
|
|
}
|
2012-02-13 00:00:56 -06:00
|
|
|
}
|