mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
Merge branch 'master' into floop-for-snapshot
This commit is contained in:
commit
a0521971b1
@ -14,6 +14,7 @@ Brendan Eich <brendan@mozilla.org>
|
||||
Brian Anderson <banderson@mozilla.com>
|
||||
Chris Double <chris.double@double.co.nz>
|
||||
Chris Peterson <cpeterson@mozilla.com>
|
||||
Damien Grassart <damien@grassart.com>
|
||||
Daniel Brooks <db48x@db48x.net>
|
||||
Daniel Luz <dev@mernen.com>
|
||||
Dave Herman <dherman@mozilla.com>
|
||||
|
@ -2,7 +2,7 @@ This is preliminary version of the Rust compiler.
|
||||
|
||||
Source layout:
|
||||
|
||||
comp/ The self-hosted compiler
|
||||
rustc/ The self-hosted compiler
|
||||
|
||||
cargo/ The package manager
|
||||
|
||||
|
@ -163,6 +163,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||
let mutbl_map =
|
||||
time(time_passes, "mutability checking",
|
||||
bind middle::mutbl::check_crate(ty_cx, crate));
|
||||
time(time_passes, "region checking",
|
||||
bind middle::regionck::check_crate(ty_cx, crate));
|
||||
let (copy_map, ref_map) =
|
||||
time(time_passes, "alias checking",
|
||||
bind middle::alias::check_crate(ty_cx, crate));
|
||||
|
71
src/rustc/middle/regionck.rs
Normal file
71
src/rustc/middle/regionck.rs
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* The region checking pass. Ensures that region-annotated pointers never
|
||||
* outlive their referents.
|
||||
*/
|
||||
|
||||
import driver::session::session;
|
||||
import middle::ty;
|
||||
import std::map::hashmap;
|
||||
import syntax::{ast, visit};
|
||||
|
||||
type ctxt = {
|
||||
tcx: ty::ctxt,
|
||||
enclosing_block: option<ast::node_id>
|
||||
};
|
||||
|
||||
fn check_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
ty::walk_ty(cx.tcx, ty::expr_ty(cx.tcx, expr)) { |t|
|
||||
alt ty::get(t).struct {
|
||||
ty::ty_rptr(region, _) {
|
||||
alt region {
|
||||
ty::re_named(_) | ty::re_caller(_) { /* ok */ }
|
||||
ty::re_block(rbi) {
|
||||
let referent_block_id = rbi;
|
||||
let enclosing_block_id = alt cx.enclosing_block {
|
||||
none {
|
||||
cx.tcx.sess.span_bug(expr.span, "block " +
|
||||
"region type outside " +
|
||||
"a block?!");
|
||||
}
|
||||
some(eb) { eb }
|
||||
};
|
||||
|
||||
let parent_blocks = cx.tcx.region_map.parent_blocks;
|
||||
while enclosing_block_id != referent_block_id {
|
||||
if parent_blocks.contains_key(referent_block_id) {
|
||||
referent_block_id =
|
||||
parent_blocks.get(referent_block_id);
|
||||
} else {
|
||||
// TODO: Enable this.
|
||||
|
||||
//cx.tcx.sess.span_err(expr.span,
|
||||
// "reference escapes " +
|
||||
// "its block");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { /* no-op */ }
|
||||
}
|
||||
}
|
||||
|
||||
visit::visit_expr(expr, cx, visitor);
|
||||
}
|
||||
|
||||
fn check_block(blk: ast::blk, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
let new_cx: ctxt = { enclosing_block: some(blk.node.id) with cx };
|
||||
visit::visit_block(blk, new_cx, visitor);
|
||||
}
|
||||
|
||||
fn check_crate(ty_cx: ty::ctxt, crate: @ast::crate) {
|
||||
let cx: ctxt = {tcx: ty_cx, enclosing_block: none};
|
||||
let visitor = visit::mk_vt(@{
|
||||
visit_expr: check_expr,
|
||||
visit_block: check_block
|
||||
with *visit::default_visitor()
|
||||
});
|
||||
visit::visit_crate(*crate, cx, visitor);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ mod middle {
|
||||
mod capture;
|
||||
mod pat_util;
|
||||
mod region;
|
||||
mod regionck;
|
||||
|
||||
mod tstate {
|
||||
mod ck;
|
||||
|
@ -9,42 +9,14 @@ import rustc::syntax::ast;
|
||||
import rustc::front::attr;
|
||||
import core::tuple;
|
||||
|
||||
export crate_attrs, basic_attrs, fn_attrs, arg_attrs,
|
||||
variant_attrs, res_attrs, method_attrs;
|
||||
export parse_crate, parse_basic, parse_fn,
|
||||
parse_variant, parse_res, parse_method;
|
||||
export crate_attrs;
|
||||
export parse_crate, parse_desc;
|
||||
export parse_hidden;
|
||||
|
||||
type crate_attrs = {
|
||||
name: option<str>
|
||||
};
|
||||
|
||||
type basic_attrs = {
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
};
|
||||
|
||||
type fn_attrs = {
|
||||
args: [arg_attrs],
|
||||
return: option<str>,
|
||||
failure: option<str>
|
||||
};
|
||||
|
||||
type arg_attrs = {
|
||||
name: str,
|
||||
desc: str
|
||||
};
|
||||
|
||||
type variant_attrs = {
|
||||
desc: option<str>
|
||||
};
|
||||
|
||||
type res_attrs = {
|
||||
args: [arg_attrs]
|
||||
};
|
||||
|
||||
type method_attrs = fn_attrs;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
@ -121,259 +93,44 @@ fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
|
||||
assert attrs.name == none;
|
||||
}
|
||||
|
||||
fn parse_basic(
|
||||
attrs: [ast::attribute]
|
||||
) -> {
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
} {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|desc|
|
||||
{
|
||||
brief: none,
|
||||
desc: desc
|
||||
}
|
||||
},
|
||||
{|_items, brief, desc|
|
||||
{
|
||||
brief: brief,
|
||||
desc: desc
|
||||
}
|
||||
}
|
||||
)
|
||||
fn parse_desc(attrs: [ast::attribute]) -> option<str> {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
attr::get_meta_item_value_str(meta)
|
||||
}
|
||||
none { none }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_handle_undocumented_mods() {
|
||||
fn parse_desc_should_handle_undocumented_mods() {
|
||||
let source = "";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.brief == none;
|
||||
assert attrs.desc == none;
|
||||
let attrs = parse_desc(attrs);
|
||||
assert attrs == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_simple_doc_attributes() {
|
||||
fn parse_desc_should_parse_simple_doc_attributes() {
|
||||
let source = "#[doc = \"basic\"]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.desc == some("basic");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_the_brief_description() {
|
||||
let source = "#[doc(brief = \"short\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.brief == some("short");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_the_long_description() {
|
||||
let source = "#[doc(desc = \"description\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.desc == some("description");
|
||||
}
|
||||
|
||||
fn parse_short_doc_or<T>(
|
||||
attrs: [ast::attribute],
|
||||
handle_short: fn&(
|
||||
short_desc: option<str>
|
||||
) -> T,
|
||||
parse_long: fn&(
|
||||
doc_items: [@ast::meta_item],
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
) -> T
|
||||
) -> T {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_value_str(meta) {
|
||||
some(desc) { handle_short(some(desc)) }
|
||||
none {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(list) {
|
||||
let brief = attr::meta_item_value_from_list(list, "brief");
|
||||
let desc = attr::meta_item_value_from_list(list, "desc");
|
||||
parse_long(list, brief, desc)
|
||||
}
|
||||
none {
|
||||
handle_short(none)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
none {
|
||||
handle_short(none)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_long_doc<T>(
|
||||
attrs: [ast::attribute],
|
||||
parse_long: fn&(doc_items: [@ast::meta_item]) -> T
|
||||
) -> T {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(list) {
|
||||
parse_long(list)
|
||||
}
|
||||
none {
|
||||
parse_long([])
|
||||
}
|
||||
}
|
||||
}
|
||||
none { parse_long([]) }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_fn(attrs: [ast::attribute]) -> fn_attrs {
|
||||
parse_long_doc(attrs, parse_fn_long_doc)
|
||||
}
|
||||
|
||||
fn parse_fn_long_doc(items: [@ast::meta_item]) -> fn_attrs {
|
||||
let return = attr::meta_item_value_from_list(items, "return");
|
||||
let failure = attr::meta_item_value_from_list(items, "failure");
|
||||
let args = parse_args(items);
|
||||
|
||||
{
|
||||
args: args,
|
||||
return: return,
|
||||
failure: failure
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_args(items: [@ast::meta_item]) -> [arg_attrs] {
|
||||
alt attr::meta_item_list_from_list(items, "args") {
|
||||
some(items) {
|
||||
vec::filter_map(items) {|item|
|
||||
option::map(attr::name_value_str_pair(item)) { |pair|
|
||||
{
|
||||
name: tuple::first(pair),
|
||||
desc: tuple::second(pair)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
none { [] }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fn_should_handle_undocumented_functions() {
|
||||
let source = "";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_fn(attrs);
|
||||
assert attrs.return == none;
|
||||
assert vec::len(attrs.args) == 0u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fn_should_parse_the_return_value_description() {
|
||||
let source = "#[doc(return = \"return value\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_fn(attrs);
|
||||
assert attrs.return == some("return value");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fn_should_parse_the_argument_descriptions() {
|
||||
let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_fn(attrs);
|
||||
assert attrs.args[0] == {name: "a", desc: "arg a"};
|
||||
assert attrs.args[1] == {name: "b", desc: "arg b"};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fn_should_parse_failure_conditions() {
|
||||
let source = "#[doc(failure = \"it's the fail\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_fn(attrs);
|
||||
assert attrs.failure == some("it's the fail");
|
||||
}
|
||||
|
||||
fn parse_variant(attrs: [ast::attribute]) -> variant_attrs {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|desc|
|
||||
{
|
||||
desc: desc
|
||||
}
|
||||
},
|
||||
{|_items, brief, desc|
|
||||
if option::is_some(brief) && option::is_some(desc) {
|
||||
// FIXME: Warn about dropping brief description
|
||||
}
|
||||
|
||||
{
|
||||
// Prefer desc over brief
|
||||
desc: option::maybe(brief, desc, {|s| some(s) })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_short_doc() {
|
||||
let source = "#[doc = \"a\"]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_brief_doc() {
|
||||
let source = "#[doc(brief = \"a\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_long_doc() {
|
||||
let source = "#[doc(desc = \"a\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
}
|
||||
|
||||
fn parse_res(attrs: [ast::attribute]) -> res_attrs {
|
||||
parse_long_doc(attrs, parse_res_long_doc)
|
||||
}
|
||||
|
||||
fn parse_res_long_doc(items: [@ast::meta_item]) -> res_attrs {
|
||||
{
|
||||
args: parse_args(items)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shoulde_parse_resource_arg() {
|
||||
let source = "#[doc(args(a = \"b\"))]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_res(attrs);
|
||||
assert attrs.args[0].name == "a";
|
||||
assert attrs.args[0].desc == "b";
|
||||
}
|
||||
|
||||
fn parse_method(attrs: [ast::attribute]) -> method_attrs {
|
||||
parse_fn(attrs)
|
||||
let attrs = parse_desc(attrs);
|
||||
assert attrs == some("basic");
|
||||
}
|
||||
|
||||
fn parse_hidden(attrs: [ast::attribute]) -> bool {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|_desc| false },
|
||||
{|metas, _brief, _desc|
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(metas) {
|
||||
let hiddens = attr::find_meta_items_by_name(metas, "hidden");
|
||||
vec::is_not_empty(hiddens)
|
||||
}
|
||||
none { false }
|
||||
}
|
||||
)
|
||||
}
|
||||
none { false }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -26,9 +26,7 @@ fn run(
|
||||
let fold = fold::fold({
|
||||
fold_crate: fold_crate,
|
||||
fold_item: fold_item,
|
||||
fold_fn: fold_fn,
|
||||
fold_enum: fold_enum,
|
||||
fold_res: fold_res,
|
||||
fold_iface: fold_iface,
|
||||
fold_impl: fold_impl
|
||||
with *fold::default_any_fold(srv)
|
||||
@ -74,18 +72,17 @@ fn fold_item(
|
||||
let srv = fold.ctxt;
|
||||
let doc = fold::default_seq_fold_item(fold, doc);
|
||||
|
||||
let attrs = if doc.id == ast::crate_node_id {
|
||||
let desc = if doc.id == ast::crate_node_id {
|
||||
// This is the top-level mod, use the crate attributes
|
||||
astsrv::exec(srv) {|ctxt|
|
||||
attr_parser::parse_basic(ctxt.ast.node.attrs)
|
||||
attr_parser::parse_desc(ctxt.ast.node.attrs)
|
||||
}
|
||||
} else {
|
||||
parse_item_attrs(srv, doc.id, attr_parser::parse_basic)
|
||||
parse_item_attrs(srv, doc.id, attr_parser::parse_desc)
|
||||
};
|
||||
|
||||
{
|
||||
brief: attrs.brief,
|
||||
desc: attrs.desc
|
||||
desc: desc
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -130,111 +127,12 @@ fn should_extract_native_fn_attributes() {
|
||||
assert doc.cratemod().nmods()[0].fns[0].desc() == some("test");
|
||||
}
|
||||
|
||||
fn fold_fn(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::fndoc
|
||||
) -> doc::fndoc {
|
||||
|
||||
let srv = fold.ctxt;
|
||||
|
||||
let doc = fold::default_seq_fold_fn(fold, doc);
|
||||
let attrs = parse_item_attrs(srv, doc.id(), attr_parser::parse_fn);
|
||||
ret merge_fn_attrs(doc, attrs);
|
||||
|
||||
fn merge_fn_attrs(
|
||||
doc: doc::fndoc,
|
||||
attrs: attr_parser::fn_attrs
|
||||
) -> doc::fndoc {
|
||||
ret {
|
||||
args: merge_arg_attrs(doc.args, attrs.args),
|
||||
return: merge_ret_attrs(doc.return, attrs.return),
|
||||
failure: attrs.failure
|
||||
with doc
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_arg_attrs(
|
||||
docs: [doc::argdoc],
|
||||
attrs: [attr_parser::arg_attrs]
|
||||
) -> [doc::argdoc] {
|
||||
par::seqmap(docs) {|doc|
|
||||
alt vec::find(attrs) {|attr|
|
||||
attr.name == doc.name
|
||||
} {
|
||||
some(attr) {
|
||||
{
|
||||
desc: some(attr.desc)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
none { doc }
|
||||
}
|
||||
}
|
||||
// FIXME: Warning when documenting a non-existent arg
|
||||
}
|
||||
|
||||
|
||||
fn merge_ret_attrs(
|
||||
doc: doc::retdoc,
|
||||
attrs: option<str>
|
||||
) -> doc::retdoc {
|
||||
{
|
||||
desc: attrs
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_fn_attributes() {
|
||||
let doc = test::mk_doc("#[doc = \"test\"] fn a() -> int { }");
|
||||
assert doc.cratemod().fns()[0].desc() == some("test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_fn_arg_attributes() {
|
||||
let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn c(a: bool) { }");
|
||||
assert doc.cratemod().fns()[0].args[0].desc == some("b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_fn_return_attributes() {
|
||||
let source = "#[doc(return = \"what\")] fn a() -> int { }";
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = tystr_pass::mk_pass().f(srv, doc);
|
||||
let fold = fold::default_any_fold(srv);
|
||||
let doc = fold_fn(fold, doc.cratemod().fns()[0]);
|
||||
assert doc.return.desc == some("what");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_preserve_fn_sig() {
|
||||
let source = "fn a() -> int { }";
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = tystr_pass::mk_pass().f(srv, doc);
|
||||
let fold = fold::default_any_fold(srv);
|
||||
let doc = fold_fn(fold, doc.cratemod().fns()[0]);
|
||||
assert doc.sig == some("fn a() -> int");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_fn_failure_conditions() {
|
||||
let doc = test::mk_doc("#[doc(failure = \"what\")] fn a() { }");
|
||||
assert doc.cratemod().fns()[0].failure == some("what");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_const_docs() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"foo\", desc = \"bar\")]\
|
||||
const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].brief() == some("foo");
|
||||
assert doc.cratemod().consts()[0].desc() == some("bar");
|
||||
}
|
||||
|
||||
fn fold_enum(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::enumdoc
|
||||
@ -246,7 +144,7 @@ fn fold_enum(
|
||||
|
||||
{
|
||||
variants: par::anymap(doc.variants) {|variant|
|
||||
let attrs = astsrv::exec(srv) {|ctxt|
|
||||
let desc = astsrv::exec(srv) {|ctxt|
|
||||
alt check ctxt.ast_map.get(doc_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_enum(ast_variants, _), _
|
||||
@ -256,13 +154,13 @@ fn fold_enum(
|
||||
v.node.name == variant.name
|
||||
});
|
||||
|
||||
attr_parser::parse_variant(ast_variant.node.attrs)
|
||||
attr_parser::parse_desc(ast_variant.node.attrs)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
desc: attrs.desc
|
||||
desc: desc
|
||||
with variant
|
||||
}
|
||||
}
|
||||
@ -272,9 +170,8 @@ fn fold_enum(
|
||||
|
||||
#[test]
|
||||
fn should_extract_enum_docs() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
|
||||
let doc = test::mk_doc("#[doc = \"b\"]\
|
||||
enum a { v }");
|
||||
assert doc.cratemod().enums()[0].brief() == some("a");
|
||||
assert doc.cratemod().enums()[0].desc() == some("b");
|
||||
}
|
||||
|
||||
@ -284,49 +181,6 @@ fn should_extract_variant_docs() {
|
||||
assert doc.cratemod().enums()[0].variants[0].desc == some("c");
|
||||
}
|
||||
|
||||
fn fold_res(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::resdoc
|
||||
) -> doc::resdoc {
|
||||
|
||||
let srv = fold.ctxt;
|
||||
let doc = fold::default_seq_fold_res(fold, doc);
|
||||
let attrs = parse_item_attrs(srv, doc.id(), attr_parser::parse_res);
|
||||
|
||||
{
|
||||
args: par::seqmap(doc.args) {|doc|
|
||||
alt vec::find(attrs.args) {|attr|
|
||||
attr.name == doc.name
|
||||
} {
|
||||
some(attr) {
|
||||
{
|
||||
desc: some(attr.desc)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
none { doc }
|
||||
}
|
||||
}
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_res_docs() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
|
||||
resource r(b: bool) { }");
|
||||
assert doc.cratemod().resources()[0].brief() == some("a");
|
||||
assert doc.cratemod().resources()[0].desc() == some("b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_res_arg_docs() {
|
||||
let doc = test::mk_doc("#[doc(args(a = \"b\"))]\
|
||||
resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].args[0].name == "a";
|
||||
assert doc.cratemod().resources()[0].args[0].desc == some("b");
|
||||
}
|
||||
|
||||
fn fold_iface(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::ifacedoc
|
||||
@ -346,30 +200,21 @@ fn merge_method_attrs(
|
||||
docs: [doc::methoddoc]
|
||||
) -> [doc::methoddoc] {
|
||||
|
||||
type method_attrs = (attr_parser::basic_attrs,
|
||||
attr_parser::method_attrs);
|
||||
|
||||
// Create an assoc list from method name to attributes
|
||||
let attrs: [(str, method_attrs)] = astsrv::exec(srv) {|ctxt|
|
||||
let attrs: [(str, option<str>)] = astsrv::exec(srv) {|ctxt|
|
||||
alt ctxt.ast_map.get(item_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_iface(_, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods) {|method|
|
||||
(method.ident,
|
||||
(attr_parser::parse_basic(method.attrs),
|
||||
attr_parser::parse_method(method.attrs)
|
||||
))
|
||||
(method.ident, attr_parser::parse_desc(method.attrs))
|
||||
}
|
||||
}
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_impl(_, _, _, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods) {|method|
|
||||
(method.ident,
|
||||
(attr_parser::parse_basic(method.attrs),
|
||||
attr_parser::parse_method(method.attrs)
|
||||
))
|
||||
(method.ident, attr_parser::parse_desc(method.attrs))
|
||||
}
|
||||
}
|
||||
_ { fail "unexpected item" }
|
||||
@ -378,15 +223,10 @@ fn merge_method_attrs(
|
||||
|
||||
vec::map2(docs, attrs) {|doc, attrs|
|
||||
assert doc.name == tuple::first(attrs);
|
||||
let basic_attrs = tuple::first(tuple::second(attrs));
|
||||
let method_attrs = tuple::second(tuple::second(attrs));
|
||||
let desc = tuple::second(attrs);
|
||||
|
||||
{
|
||||
brief: basic_attrs.brief,
|
||||
desc: basic_attrs.desc,
|
||||
args: merge_arg_attrs(doc.args, method_attrs.args),
|
||||
return: merge_ret_attrs(doc.return, method_attrs.return),
|
||||
failure: method_attrs.failure
|
||||
desc: desc
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -402,20 +242,10 @@ fn should_extract_iface_docs() {
|
||||
fn should_extract_iface_method_docs() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i {\
|
||||
#[doc(\
|
||||
brief = \"brief\",\
|
||||
desc = \"desc\",\
|
||||
args(a = \"a\"),\
|
||||
return = \"return\",\
|
||||
failure = \"failure\")]\
|
||||
#[doc = \"desc\"]\
|
||||
fn f(a: bool) -> bool;\
|
||||
}");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].brief == some("brief");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].desc == some("desc");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].args[0].desc == some("a");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].return.desc
|
||||
== some("return");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].failure == some("failure");
|
||||
}
|
||||
|
||||
|
||||
@ -443,28 +273,10 @@ fn should_extract_impl_docs() {
|
||||
fn should_extract_impl_method_docs() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int {\
|
||||
#[doc(\
|
||||
brief = \"brief\",\
|
||||
desc = \"desc\",\
|
||||
args(a = \"a\"),\
|
||||
return = \"return\",\
|
||||
failure = \"failure\")]\
|
||||
#[doc = \"desc\"]\
|
||||
fn f(a: bool) -> bool { }\
|
||||
}");
|
||||
assert doc.cratemod().impls()[0].methods[0].brief == some("brief");
|
||||
assert doc.cratemod().impls()[0].methods[0].desc == some("desc");
|
||||
assert doc.cratemod().impls()[0].methods[0].args[0].desc == some("a");
|
||||
assert doc.cratemod().impls()[0].methods[0].return.desc == some("return");
|
||||
assert doc.cratemod().impls()[0].methods[0].failure == some("failure");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_type_docs() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \"brief\", desc = \"desc\")]\
|
||||
type t = int;");
|
||||
assert doc.cratemod().types()[0].brief() == some("brief");
|
||||
assert doc.cratemod().types()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -33,106 +33,94 @@ fn take_my_order_please(
|
||||
_order: [omnomnomy]
|
||||
) -> uint {
|
||||
|
||||
#[doc(
|
||||
desc = "OMG would you take my order already?",
|
||||
args(_waitress = "The waitress that you want to bother",
|
||||
_order = "The order vector. It should be filled with food."),
|
||||
return = "The price of the order, including tax",
|
||||
failure = "This function is full of fail"
|
||||
)];
|
||||
#[doc = "
|
||||
OMG would you take my order already?
|
||||
|
||||
fail;
|
||||
}
|
||||
# Arguments
|
||||
|
||||
fn take_my_order_now(
|
||||
_waitress: waitress,
|
||||
_order: [omnomnomy]
|
||||
) -> uint {
|
||||
* _waitress - The waitress that you want to bother
|
||||
* _order - The order vector. It should be filled with food
|
||||
|
||||
#[doc(
|
||||
desc = "OMG would you take my order already?",
|
||||
args(_waitress = "The waitress that you want to bother",
|
||||
_order = "The order vector. It should be filled with food."),
|
||||
return = "
|
||||
# Return
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
|
||||
nec molestie nisl. Duis massa risus, pharetra a scelerisque a,
|
||||
molestie eu velit. Donec mattis ligula at ante imperdiet ut
|
||||
dapibus mauris malesuada.
|
||||
The price of the order, including tax
|
||||
|
||||
Sed gravida nisi a metus elementum sit amet hendrerit dolor
|
||||
bibendum. Aenean sit amet neque massa, sed tempus tortor. Sed
|
||||
ut lobortis enim. Proin a mauris quis nunc fermentum ultrices
|
||||
eget a erat. Mauris in lectus vitae metus sodales
|
||||
auctor. Morbi nunc quam, ultricies at venenatis non,
|
||||
pellentesque ac dui.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
|
||||
molestie nisl. Duis massa risus, pharetra a scelerisque a,
|
||||
molestie eu velit. Donec mattis ligula at ante imperdiet ut
|
||||
dapibus mauris malesuada.
|
||||
|
||||
",
|
||||
failure = "This function is full of fail"
|
||||
)];
|
||||
Sed gravida nisi a metus elementum sit amet hendrerit dolor
|
||||
bibendum. Aenean sit amet neque massa, sed tempus tortor. Sed ut
|
||||
lobortis enim. Proin a mauris quis nunc fermentum ultrices eget a
|
||||
erat. Mauris in lectus vitae metus sodales auctor. Morbi nunc
|
||||
quam, ultricies at venenatis non, pellentesque ac dui.
|
||||
|
||||
# Failure
|
||||
|
||||
This function is full of fail
|
||||
"];
|
||||
|
||||
fail;
|
||||
}
|
||||
|
||||
mod fortress_of_solitude {
|
||||
#[doc(
|
||||
brief = "Superman's vacation home",
|
||||
desc = "
|
||||
#[doc = "
|
||||
Superman's vacation home
|
||||
|
||||
The fortress of solitude is located in the Arctic and it is
|
||||
cold. What you may not know about the fortress of solitude
|
||||
though is that it contains two separate bowling alleys. One of
|
||||
them features bumper-bowling and is kind of lame.
|
||||
The fortress of solitude is located in the Arctic and it is
|
||||
cold. What you may not know about the fortress of solitude
|
||||
though is that it contains two separate bowling alleys. One of
|
||||
them features bumper-bowling and is kind of lame.
|
||||
|
||||
Really, it's pretty cool.
|
||||
Really, it's pretty cool.
|
||||
|
||||
")];
|
||||
"];
|
||||
|
||||
}
|
||||
|
||||
mod blade_runner {
|
||||
#[doc(
|
||||
brief = "Blade Runner is probably the best movie ever",
|
||||
desc = "I like that in the world of Blade Runner it is always
|
||||
raining, and that it's always night time. And Aliens
|
||||
was also a really good movie.
|
||||
#[doc = "
|
||||
Blade Runner is probably the best movie ever
|
||||
|
||||
Alien 3 was crap though."
|
||||
)];
|
||||
I like that in the world of Blade Runner it is always
|
||||
raining, and that it's always night time. And Aliens
|
||||
was also a really good movie.
|
||||
|
||||
Alien 3 was crap though.
|
||||
"];
|
||||
}
|
||||
|
||||
#[doc(
|
||||
brief = "Bored",
|
||||
desc = "
|
||||
#[doc = "
|
||||
Bored
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
|
||||
molestie nisl. Duis massa risus, pharetra a scelerisque a,
|
||||
molestie eu velit. Donec mattis ligula at ante imperdiet ut
|
||||
dapibus mauris malesuada. Sed gravida nisi a metus elementum sit
|
||||
amet hendrerit dolor bibendum. Aenean sit amet neque massa, sed
|
||||
tempus tortor. Sed ut lobortis enim. Proin a mauris quis nunc
|
||||
fermentum ultrices eget a erat. Mauris in lectus vitae metus
|
||||
sodales auctor. Morbi nunc quam, ultricies at venenatis non,
|
||||
pellentesque ac dui.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
|
||||
molestie nisl. Duis massa risus, pharetra a scelerisque a,
|
||||
molestie eu velit. Donec mattis ligula at ante imperdiet ut
|
||||
dapibus mauris malesuada. Sed gravida nisi a metus elementum sit
|
||||
amet hendrerit dolor bibendum. Aenean sit amet neque massa, sed
|
||||
tempus tortor. Sed ut lobortis enim. Proin a mauris quis nunc
|
||||
fermentum ultrices eget a erat. Mauris in lectus vitae metus
|
||||
sodales auctor. Morbi nunc quam, ultricies at venenatis non,
|
||||
pellentesque ac dui.
|
||||
|
||||
Quisque vitae est id eros placerat laoreet sit amet eu
|
||||
nisi. Curabitur suscipit neque porttitor est euismod
|
||||
lacinia. Curabitur non quam vitae ipsum adipiscing
|
||||
condimentum. Mauris ut ante eget metus sollicitudin
|
||||
blandit. Aliquam erat volutpat. Morbi sed nisl mauris. Nulla
|
||||
facilisi. Phasellus at mollis ipsum. Maecenas sed convallis
|
||||
sapien. Nullam in ligula turpis. Pellentesque a neque augue. Sed
|
||||
eget ante feugiat tortor congue auctor ac quis ante. Proin
|
||||
condimentum lacinia tincidunt.
|
||||
Quisque vitae est id eros placerat laoreet sit amet eu
|
||||
nisi. Curabitur suscipit neque porttitor est euismod
|
||||
lacinia. Curabitur non quam vitae ipsum adipiscing
|
||||
condimentum. Mauris ut ante eget metus sollicitudin
|
||||
blandit. Aliquam erat volutpat. Morbi sed nisl mauris. Nulla
|
||||
facilisi. Phasellus at mollis ipsum. Maecenas sed convallis
|
||||
sapien. Nullam in ligula turpis. Pellentesque a neque augue. Sed
|
||||
eget ante feugiat tortor congue auctor ac quis ante. Proin
|
||||
condimentum lacinia tincidunt.
|
||||
|
||||
")]
|
||||
"]
|
||||
resource bored(bored: bool) {
|
||||
log(error, bored);
|
||||
}
|
||||
|
||||
#[doc(
|
||||
brief = "The Shunned House",
|
||||
desc = "
|
||||
#[doc = "
|
||||
The Shunned House
|
||||
|
||||
From even the greatest of horrors irony is seldom absent. Sometimes it
|
||||
enters directly into the composition of the events, while sometimes it
|
||||
@ -147,11 +135,9 @@ northward along the same street to Mrs. Whitman's home and the
|
||||
neighboring hillside churchyard of St. John's, whose hidden expanse of
|
||||
Eighteenth Century gravestones had for him a peculiar fascination.
|
||||
|
||||
")]
|
||||
"]
|
||||
iface the_shunned_house {
|
||||
#[doc(
|
||||
desc = "
|
||||
|
||||
#[doc = "
|
||||
Now the irony is this. In this walk, so many times repeated, the
|
||||
world's greatest master of the terrible and the bizarre was
|
||||
obliged to pass a particular house on the eastern side of the
|
||||
@ -165,17 +151,14 @@ iface the_shunned_house {
|
||||
unknowingly, and stands starkly leering as a symbol of all that is
|
||||
unutterably hideous.
|
||||
|
||||
",
|
||||
args(
|
||||
a =
|
||||
"A yard dating from a time when the region was partly
|
||||
open country"
|
||||
))]
|
||||
# Arguments
|
||||
|
||||
* unkempt_yard - A yard dating from a time when the region was partly
|
||||
open country
|
||||
"]
|
||||
fn dingy_house(unkempt_yard: int);
|
||||
|
||||
#[doc(
|
||||
desc = "
|
||||
|
||||
#[doc = "
|
||||
The house was--and for that matter still is--of a kind to attract
|
||||
the attention of the curious. Originally a farm or semi-farm
|
||||
building, it followed the average New England colonial lines of
|
||||
@ -191,17 +174,12 @@ iface the_shunned_house {
|
||||
the graveyards of the first settlers, and straightened only when
|
||||
the removal of the bodies to the North Burial Ground made it
|
||||
decently possible to cut through the old family plots.
|
||||
|
||||
",
|
||||
return = "A dingy house with an unkempt yard",
|
||||
failure = "Will fail if bodies are removed from premises"
|
||||
)]
|
||||
"]
|
||||
fn construct() -> bool;
|
||||
}
|
||||
|
||||
#[doc = "Whatever"]
|
||||
impl of the_shunned_house for omnomnomy {
|
||||
#[doc(args(_unkempt_yard = "Whatever"))]
|
||||
fn dingy_house(_unkempt_yard: int) {
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,9 @@ fn run(
|
||||
|
||||
fn fold_item(fold: fold::fold<()>, doc: doc::itemdoc) -> doc::itemdoc {
|
||||
let doc = fold::default_seq_fold_item(fold, doc);
|
||||
let (brief, desc) = modify(doc.brief, doc.desc);
|
||||
|
||||
{
|
||||
brief: brief,
|
||||
desc: desc
|
||||
brief: extract(doc.desc)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -45,11 +43,8 @@ fn fold_iface(fold: fold::fold<()>, doc: doc::ifacedoc) -> doc::ifacedoc {
|
||||
|
||||
{
|
||||
methods: par::anymap(doc.methods) {|doc|
|
||||
let (brief, desc) = modify(doc.brief, doc.desc);
|
||||
|
||||
{
|
||||
brief: brief,
|
||||
desc: desc
|
||||
brief: extract(doc.desc)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -62,11 +57,8 @@ fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
|
||||
|
||||
{
|
||||
methods: par::anymap(doc.methods) {|doc|
|
||||
let (brief, desc) = modify(doc.brief, doc.desc);
|
||||
|
||||
{
|
||||
brief: brief,
|
||||
desc: desc
|
||||
brief: extract(doc.desc)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -75,76 +67,22 @@ fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_mod_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] mod m { }");
|
||||
fn should_promote_desc() {
|
||||
let doc = test::mk_doc("#[doc = \"desc\"] mod m { }");
|
||||
assert doc.cratemod().mods()[0].brief() == some("desc");
|
||||
assert doc.cratemod().mods()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_const_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].brief() == some("desc");
|
||||
assert doc.cratemod().consts()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_fn_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] fn a() { }");
|
||||
assert doc.cratemod().fns()[0].brief() == some("desc");
|
||||
assert doc.cratemod().fns()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_enum_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] enum a { b }");
|
||||
assert doc.cratemod().enums()[0].brief() == some("desc");
|
||||
assert doc.cratemod().enums()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_resource_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \"desc\")] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].brief() == some("desc");
|
||||
assert doc.cratemod().resources()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_iface_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] iface i { fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].brief() == some("desc");
|
||||
assert doc.cratemod().ifaces()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_iface_method_desc() {
|
||||
let doc = test::mk_doc("iface i { #[doc(desc = \"desc\")] fn a(); }");
|
||||
let doc = test::mk_doc("iface i { #[doc = \"desc\"] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].brief == some("desc");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].desc == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_impl_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \"desc\")] impl i for int { fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].brief() == some("desc");
|
||||
assert doc.cratemod().impls()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_impl_method_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(desc = \"desc\")] fn a() { } }");
|
||||
"impl i for int { #[doc = \"desc\"] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].brief == some("desc");
|
||||
assert doc.cratemod().impls()[0].methods[0].desc == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_promote_type_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \"desc\")] type t = int;");
|
||||
assert doc.cratemod().types()[0].brief() == some("desc");
|
||||
assert doc.cratemod().types()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -158,42 +96,44 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
fn modify(
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
) -> (option<str>, option<str>) {
|
||||
|
||||
if option::is_some(brief) || option::is_none(desc) {
|
||||
ret (brief, desc);
|
||||
fn extract(desc: option<str>) -> option<str> {
|
||||
if option::is_none(desc) {
|
||||
ret none
|
||||
}
|
||||
|
||||
parse_desc(option::get(desc))
|
||||
}
|
||||
|
||||
fn parse_desc(desc: str) -> (option<str>, option<str>) {
|
||||
fn parse_desc(desc: str) -> option<str> {
|
||||
|
||||
const max_brief_len: uint = 120u;
|
||||
|
||||
let paras = paragraphs(desc);
|
||||
|
||||
if check vec::is_not_empty(paras) {
|
||||
let maybe_brief = vec::head(paras);
|
||||
if str::len(maybe_brief) <= max_brief_len {
|
||||
let desc_paras = vec::tail(paras);
|
||||
let desc = if vec::is_not_empty(desc_paras) {
|
||||
some(str::connect(desc_paras, "\n\n"))
|
||||
} else {
|
||||
none
|
||||
};
|
||||
(some(maybe_brief), desc)
|
||||
alt first_sentence(desc) {
|
||||
some(first_sentence) {
|
||||
if str::len(first_sentence) <= max_brief_len {
|
||||
some(first_sentence)
|
||||
} else {
|
||||
(none, some(desc))
|
||||
none
|
||||
}
|
||||
} else {
|
||||
(none, none)
|
||||
}
|
||||
none { none }
|
||||
}
|
||||
}
|
||||
|
||||
fn first_sentence(s: str) -> option<str> {
|
||||
let paras = paragraphs(s);
|
||||
if vec::is_not_empty(paras) {
|
||||
let first = vec::head(sentences(vec::head(paras)));
|
||||
some(str::replace(first, "\n", " "))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
fn sentences(s: str) -> [str] {
|
||||
str::split_char(s, '.')
|
||||
}
|
||||
|
||||
fn paragraphs(s: str) -> [str] {
|
||||
let lines = str::lines_any(s);
|
||||
let whitespace_lines = 0;
|
||||
@ -244,42 +184,36 @@ fn test_paragraphs_2() {
|
||||
|
||||
#[test]
|
||||
fn should_promote_short_descs() {
|
||||
let brief = none;
|
||||
let desc = some("desc");
|
||||
let (newbrief, newdesc) = modify(brief, desc);
|
||||
assert newbrief == desc;
|
||||
assert newdesc == none;
|
||||
let brief = extract(desc);
|
||||
assert brief == desc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_promote_long_descs() {
|
||||
let brief = none;
|
||||
let desc = some("Warkworth Castle is a ruined medieval building
|
||||
in the town of the same name in the English county of Northumberland.
|
||||
The town and castle occupy a loop of the River Coquet, less than a mile
|
||||
in the town of the same name in the English county of Northumberland,
|
||||
and the town and castle occupy a loop of the River Coquet, less than a mile
|
||||
from England's north-east coast. When the castle was founded is uncertain,
|
||||
but traditionally its construction has been ascribed to Prince Henry of
|
||||
Scotland in the mid 12th century, although it may have been built by
|
||||
King Henry II of England when he took control of England'snorthern
|
||||
counties.");
|
||||
let (newbrief, _) = modify(brief, desc);
|
||||
assert newbrief == none;
|
||||
let brief = extract(desc);
|
||||
assert brief == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_promote_descs_over_brief() {
|
||||
let brief = some("brief");
|
||||
let desc = some("desc");
|
||||
let (newbrief, newdesc) = modify(brief, desc);
|
||||
assert newbrief == brief;
|
||||
assert newdesc == desc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_brief_from_desc() {
|
||||
let brief = none;
|
||||
let desc = some("brief\n\ndesc");
|
||||
let (newbrief, newdesc) = modify(brief, desc);
|
||||
assert newbrief == some("brief");
|
||||
assert newdesc == some("desc");
|
||||
}
|
||||
fn should_promote_first_sentence() {
|
||||
let desc = some("Warkworth Castle is a ruined medieval building
|
||||
in the town. of the same name in the English county of Northumberland,
|
||||
and the town and castle occupy a loop of the River Coquet, less than a mile
|
||||
from England's north-east coast. When the castle was founded is uncertain,
|
||||
but traditionally its construction has been ascribed to Prince Henry of
|
||||
Scotland in the mid 12th century, although it may have been built by
|
||||
King Henry II of England when he took control of England'snorthern
|
||||
counties.");
|
||||
let brief = extract(desc);
|
||||
assert brief == some(
|
||||
"Warkworth Castle is a ruined medieval building in the town");
|
||||
}
|
@ -11,6 +11,15 @@ enum page {
|
||||
itempage(itemtag)
|
||||
}
|
||||
|
||||
#[doc = "
|
||||
Most rustdocs can be parsed into 'sections' according to their markdown
|
||||
headers
|
||||
"]
|
||||
type section = {
|
||||
header: str,
|
||||
body: str
|
||||
};
|
||||
|
||||
// FIXME: We currently give topmod the name of the crate. There would
|
||||
// probably be fewer special cases if the crate had its own name and
|
||||
// topmod's name was the empty string.
|
||||
@ -36,10 +45,16 @@ type itemdoc = {
|
||||
path: [str],
|
||||
brief: option<str>,
|
||||
desc: option<str>,
|
||||
sections: [section],
|
||||
// Indicates that this node is a reexport of a different item
|
||||
reexport: bool
|
||||
};
|
||||
|
||||
type simpleitemdoc = {
|
||||
item: itemdoc,
|
||||
sig: option<str>
|
||||
};
|
||||
|
||||
type moddoc = {
|
||||
item: itemdoc,
|
||||
items: [itemtag],
|
||||
@ -51,27 +66,9 @@ type nmoddoc = {
|
||||
fns: [fndoc]
|
||||
};
|
||||
|
||||
type constdoc = {
|
||||
item: itemdoc,
|
||||
ty: option<str>
|
||||
};
|
||||
type constdoc = simpleitemdoc;
|
||||
|
||||
type fndoc = {
|
||||
item: itemdoc,
|
||||
args: [argdoc],
|
||||
return: retdoc,
|
||||
failure: option<str>,
|
||||
sig: option<str>
|
||||
};
|
||||
|
||||
type argdoc = {
|
||||
name: str,
|
||||
desc: option<str>
|
||||
};
|
||||
|
||||
type retdoc = {
|
||||
desc: option<str>
|
||||
};
|
||||
type fndoc = simpleitemdoc;
|
||||
|
||||
type enumdoc = {
|
||||
item: itemdoc,
|
||||
@ -84,11 +81,7 @@ type variantdoc = {
|
||||
sig: option<str>
|
||||
};
|
||||
|
||||
type resdoc = {
|
||||
item: itemdoc,
|
||||
args: [argdoc],
|
||||
sig: option<str>
|
||||
};
|
||||
type resdoc = simpleitemdoc;
|
||||
|
||||
type ifacedoc = {
|
||||
item: itemdoc,
|
||||
@ -99,9 +92,7 @@ type methoddoc = {
|
||||
name: str,
|
||||
brief: option<str>,
|
||||
desc: option<str>,
|
||||
args: [argdoc],
|
||||
return: retdoc,
|
||||
failure: option<str>,
|
||||
sections: [section],
|
||||
sig: option<str>
|
||||
};
|
||||
|
||||
@ -112,10 +103,7 @@ type impldoc = {
|
||||
methods: [methoddoc]
|
||||
};
|
||||
|
||||
type tydoc = {
|
||||
item: itemdoc,
|
||||
sig: option<str>
|
||||
};
|
||||
type tydoc = simpleitemdoc;
|
||||
|
||||
type index = {
|
||||
entries: [index_entry]
|
||||
@ -344,6 +332,10 @@ impl of item for itemtag {
|
||||
}
|
||||
}
|
||||
|
||||
impl of item for simpleitemdoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for moddoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
@ -352,22 +344,10 @@ impl of item for nmoddoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for fndoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for constdoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for enumdoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for resdoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for ifacedoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
@ -376,10 +356,6 @@ impl of item for impldoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl of item for tydoc {
|
||||
fn item() -> itemdoc { self.item }
|
||||
}
|
||||
|
||||
impl util<A:item> for A {
|
||||
fn id() -> ast_id {
|
||||
self.item().id
|
||||
@ -400,4 +376,8 @@ impl util<A:item> for A {
|
||||
fn desc() -> option<str> {
|
||||
self.item().desc
|
||||
}
|
||||
|
||||
fn sections() -> [section] {
|
||||
self.item().sections
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@ fn mk_itemdoc(id: ast::node_id, name: ast::ident) -> doc::itemdoc {
|
||||
path: [],
|
||||
brief: none,
|
||||
desc: none,
|
||||
sections: [],
|
||||
reexport: false
|
||||
}
|
||||
}
|
||||
@ -67,9 +68,9 @@ fn moddoc_from_mod(
|
||||
nmoddoc_from_mod(itemdoc, nm)
|
||||
))
|
||||
}
|
||||
ast::item_fn(decl, _, _) {
|
||||
ast::item_fn(_, _, _) {
|
||||
some(doc::fntag(
|
||||
fndoc_from_fn(itemdoc, decl)
|
||||
fndoc_from_fn(itemdoc)
|
||||
))
|
||||
}
|
||||
ast::item_const(_, _) {
|
||||
@ -82,9 +83,9 @@ fn moddoc_from_mod(
|
||||
enumdoc_from_enum(itemdoc, variants)
|
||||
))
|
||||
}
|
||||
ast::item_res(decl, _, _, _, _) {
|
||||
ast::item_res(_, _, _, _, _) {
|
||||
some(doc::restag(
|
||||
resdoc_from_resource(itemdoc, decl)
|
||||
resdoc_from_resource(itemdoc)
|
||||
))
|
||||
}
|
||||
ast::item_iface(_, methods) {
|
||||
@ -120,54 +121,25 @@ fn nmoddoc_from_mod(
|
||||
fns: par::seqmap(module.items) {|item|
|
||||
let itemdoc = mk_itemdoc(item.id, item.ident);
|
||||
alt item.node {
|
||||
ast::native_item_fn(decl, _) {
|
||||
fndoc_from_fn(itemdoc, decl)
|
||||
ast::native_item_fn(_, _) {
|
||||
fndoc_from_fn(itemdoc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fndoc_from_fn(
|
||||
itemdoc: doc::itemdoc,
|
||||
decl: ast::fn_decl
|
||||
) -> doc::fndoc {
|
||||
fn fndoc_from_fn(itemdoc: doc::itemdoc) -> doc::fndoc {
|
||||
{
|
||||
item: itemdoc,
|
||||
args: argdocs_from_args(decl.inputs),
|
||||
return: {
|
||||
desc: none
|
||||
},
|
||||
failure: none,
|
||||
sig: none
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_fn_args() {
|
||||
let source = "fn a(b: int, c: int) { }";
|
||||
let ast = parse::from_str(source);
|
||||
let doc = extract(ast, "");
|
||||
let fn_ = doc.cratemod().fns()[0];
|
||||
assert fn_.args[0].name == "b";
|
||||
assert fn_.args[1].name == "c";
|
||||
}
|
||||
|
||||
fn argdocs_from_args(args: [ast::arg]) -> [doc::argdoc] {
|
||||
par::seqmap(args, argdoc_from_arg)
|
||||
}
|
||||
|
||||
fn argdoc_from_arg(arg: ast::arg) -> doc::argdoc {
|
||||
{
|
||||
name: arg.ident,
|
||||
desc: none
|
||||
}
|
||||
}
|
||||
|
||||
fn constdoc_from_const(itemdoc: doc::itemdoc) -> doc::constdoc {
|
||||
{
|
||||
item: itemdoc,
|
||||
ty: none
|
||||
sig: none
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,13 +187,9 @@ fn should_extract_enum_variants() {
|
||||
assert doc.cratemod().enums()[0].variants[0].name == "v";
|
||||
}
|
||||
|
||||
fn resdoc_from_resource(
|
||||
itemdoc: doc::itemdoc,
|
||||
decl: ast::fn_decl
|
||||
) -> doc::resdoc {
|
||||
fn resdoc_from_resource(itemdoc: doc::itemdoc) -> doc::resdoc {
|
||||
{
|
||||
item: itemdoc,
|
||||
args: argdocs_from_args(decl.inputs),
|
||||
sig: none
|
||||
}
|
||||
}
|
||||
@ -233,12 +201,6 @@ fn should_extract_resources() {
|
||||
assert doc.cratemod().resources()[0].name() == "r";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_resource_args() {
|
||||
let doc = test::mk_doc("resource r(b: bool) { }");
|
||||
assert doc.cratemod().resources()[0].args[0].name == "b";
|
||||
}
|
||||
|
||||
fn ifacedoc_from_iface(
|
||||
itemdoc: doc::itemdoc,
|
||||
methods: [ast::ty_method]
|
||||
@ -250,11 +212,7 @@ fn ifacedoc_from_iface(
|
||||
name: method.ident,
|
||||
brief: none,
|
||||
desc: none,
|
||||
args: argdocs_from_args(method.decl.inputs),
|
||||
return: {
|
||||
desc: none
|
||||
},
|
||||
failure: none,
|
||||
sections: [],
|
||||
sig: none
|
||||
}
|
||||
}
|
||||
@ -273,12 +231,6 @@ fn should_extract_iface_methods() {
|
||||
assert doc.cratemod().ifaces()[0].methods[0].name == "f";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_iface_method_args() {
|
||||
let doc = test::mk_doc("iface i { fn f(a: bool); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].args[0].name == "a";
|
||||
}
|
||||
|
||||
fn impldoc_from_impl(
|
||||
itemdoc: doc::itemdoc,
|
||||
methods: [@ast::method]
|
||||
@ -292,11 +244,7 @@ fn impldoc_from_impl(
|
||||
name: method.ident,
|
||||
brief: none,
|
||||
desc: none,
|
||||
args: argdocs_from_args(method.decl.inputs),
|
||||
return: {
|
||||
desc: none
|
||||
},
|
||||
failure: none,
|
||||
sections: [],
|
||||
sig: none
|
||||
}
|
||||
}
|
||||
@ -321,12 +269,6 @@ fn should_extract_impl_methods() {
|
||||
assert doc.cratemod().impls()[0].methods[0].name == "f";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_impl_method_args() {
|
||||
let doc = test::mk_doc("impl i for int { fn f(a: bool) { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].args[0].name == "a";
|
||||
}
|
||||
|
||||
fn tydoc_from_ty(
|
||||
itemdoc: doc::itemdoc
|
||||
) -> doc::tydoc {
|
||||
|
@ -145,7 +145,7 @@ fn should_index_mod_contents_multi_page() {
|
||||
fn should_add_brief_desc_to_index() {
|
||||
let doc = test::mk_doc(
|
||||
config::doc_per_mod,
|
||||
"#[doc(brief = \"test\")] mod a { }"
|
||||
"#[doc = \"test\"] mod a { }"
|
||||
);
|
||||
assert option::get(doc.cratemod().index).entries[0].brief == some("test");
|
||||
}
|
||||
@ -160,6 +160,7 @@ mod test {
|
||||
};
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
let doc = path_pass::mk_pass().f(srv, doc);
|
||||
run(srv, doc, config)
|
||||
}
|
||||
|
@ -120,7 +120,8 @@ fn should_request_new_writer_for_each_page() {
|
||||
enum hlvl {
|
||||
h1 = 1,
|
||||
h2 = 2,
|
||||
h3 = 3
|
||||
h3 = 3,
|
||||
h4 = 4
|
||||
}
|
||||
|
||||
fn write_header(ctxt: ctxt, lvl: hlvl, doc: doc::itemtag) {
|
||||
@ -238,12 +239,55 @@ fn should_write_full_path_to_mod() {
|
||||
assert str::contains(markdown, "# Module `a::b::c`");
|
||||
}
|
||||
|
||||
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>
|
||||
) {
|
||||
alt desc {
|
||||
some(desc) {
|
||||
ctxt.w.write_line(desc);
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
none { }
|
||||
}
|
||||
}
|
||||
|
||||
fn write_sections(ctxt: ctxt, sections: [doc::section]) {
|
||||
vec::iter(sections) {|section|
|
||||
write_section(ctxt, section);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_section(ctxt: ctxt, section: doc::section) {
|
||||
write_header_(ctxt, h4, section.header);
|
||||
ctxt.w.write_line(section.body);
|
||||
ctxt.w.write_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
|
||||
) {
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
if option::is_some(doc.index) {
|
||||
write_index(ctxt, option::get(doc.index));
|
||||
}
|
||||
@ -267,12 +311,6 @@ fn write_item(ctxt: ctxt, doc: doc::itemtag) {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_crate_brief_description() {
|
||||
let markdown = test::render("#[doc(brief = \"this is the crate\")];");
|
||||
assert str::contains(markdown, "this is the crate");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_crate_description() {
|
||||
let markdown = test::render("#[doc = \"this is the crate\"];");
|
||||
@ -309,7 +347,7 @@ fn should_write_index() {
|
||||
|
||||
#[test]
|
||||
fn should_write_index_brief() {
|
||||
let markdown = test::render("#[doc(brief = \"test\")] mod a { }");
|
||||
let markdown = test::render("#[doc = \"test\"] mod a { }");
|
||||
assert str::contains(markdown, "(#module-a) - test\n");
|
||||
}
|
||||
|
||||
@ -321,9 +359,7 @@ fn should_not_write_index_if_no_entries() {
|
||||
|
||||
fn write_nmod(ctxt: ctxt, doc: doc::nmoddoc) {
|
||||
write_header(ctxt, h1, doc::nmodtag(doc));
|
||||
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
|
||||
for fndoc in doc.fns {
|
||||
write_fn(ctxt, fndoc);
|
||||
@ -351,29 +387,19 @@ fn write_fn(
|
||||
write_fnlike(
|
||||
ctxt,
|
||||
doc.sig,
|
||||
doc.brief(),
|
||||
doc.desc(),
|
||||
doc.args,
|
||||
doc.return,
|
||||
doc.failure
|
||||
doc.sections()
|
||||
);
|
||||
}
|
||||
|
||||
fn write_fnlike(
|
||||
ctxt: ctxt,
|
||||
sig: option<str>,
|
||||
brief: option<str>,
|
||||
desc: option<str>,
|
||||
args: [doc::argdoc],
|
||||
return: doc::retdoc,
|
||||
failure: option<str>
|
||||
sections: [doc::section]
|
||||
) {
|
||||
write_sig(ctxt, sig);
|
||||
write_brief(ctxt, brief);
|
||||
write_desc(ctxt, desc);
|
||||
write_args(ctxt, args);
|
||||
write_return(ctxt, return);
|
||||
write_failure(ctxt, failure);
|
||||
write_common(ctxt, desc, sections);
|
||||
}
|
||||
|
||||
fn write_sig(ctxt: ctxt, sig: option<str>) {
|
||||
@ -433,167 +459,8 @@ fn should_correctly_indent_fn_signature() {
|
||||
|
||||
#[test]
|
||||
fn should_leave_blank_line_between_fn_header_and_sig() {
|
||||
let markdown = test::render("#[doc(brief = \"brief\")] fn a() { }");
|
||||
assert str::contains(markdown, "Function `a`\n\n fn a()");
|
||||
}
|
||||
|
||||
fn write_brief(
|
||||
ctxt: ctxt,
|
||||
brief: option<str>
|
||||
) {
|
||||
alt brief {
|
||||
some(brief) {
|
||||
ctxt.w.write_line(brief);
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
none { }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_leave_blank_line_after_brief() {
|
||||
let markdown = test::render("#[doc(brief = \"brief\")] fn a() { }");
|
||||
assert str::contains(markdown, "brief\n\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_leave_blank_line_between_brief_and_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
|
||||
);
|
||||
assert str::contains(markdown, "brief\n\ndesc");
|
||||
}
|
||||
|
||||
fn write_desc(
|
||||
ctxt: ctxt,
|
||||
desc: option<str>
|
||||
) {
|
||||
alt desc {
|
||||
some(desc) {
|
||||
ctxt.w.write_line(desc);
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
none { }
|
||||
}
|
||||
}
|
||||
|
||||
fn write_args(
|
||||
ctxt: ctxt,
|
||||
args: [doc::argdoc]
|
||||
) {
|
||||
if vec::is_not_empty(args) {
|
||||
write_lead(ctxt, "Arguments");
|
||||
ctxt.w.write_line("");
|
||||
ctxt.w.write_line("");
|
||||
vec::iter(args) {|arg| write_arg(ctxt, arg) };
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
}
|
||||
|
||||
fn write_arg(ctxt: ctxt, arg: doc::argdoc) {
|
||||
ctxt.w.write_str(#fmt(
|
||||
"* `%s`",
|
||||
arg.name
|
||||
));
|
||||
alt arg.desc {
|
||||
some(desc) {
|
||||
ctxt.w.write_str(#fmt(" - %s", desc));
|
||||
}
|
||||
none { }
|
||||
}
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_argument_list() {
|
||||
let source = "fn a(b: int, c: int) { }";
|
||||
let markdown = test::render(source);
|
||||
assert str::contains(
|
||||
markdown,
|
||||
"__Arguments__: \n\
|
||||
\n\
|
||||
* `b`\n\
|
||||
* `c`\n\
|
||||
\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_write_arguments_if_none() {
|
||||
let source = "fn a() { } fn b() { }";
|
||||
let markdown = test::render(source);
|
||||
assert !str::contains(markdown, "Arguments");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_argument_description() {
|
||||
let source = "#[doc(args(a = \"milk\"))] fn f(a: bool) { }";
|
||||
let markdown = test::render(source);
|
||||
assert str::contains(markdown, "`a` - milk");
|
||||
}
|
||||
|
||||
fn write_return(
|
||||
ctxt: ctxt,
|
||||
doc: doc::retdoc
|
||||
) {
|
||||
alt doc.desc {
|
||||
some(d) {
|
||||
write_lead(ctxt, "Return value");
|
||||
ctxt.w.write_line(d);
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
none { }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_return_type_on_new_line() {
|
||||
let markdown = test::render(
|
||||
"#[doc(return = \"test\")] fn a() -> int { }");
|
||||
assert str::contains(markdown, "\n__Return value__: test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_blank_line_between_return_type_and_next_header() {
|
||||
let markdown = test::render(
|
||||
"#[doc(return = \"test\")] fn a() -> int { } \
|
||||
fn b() -> int { }"
|
||||
);
|
||||
assert str::contains(markdown, "__Return value__: test\n\n##");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_write_return_type_when_there_is_none() {
|
||||
let markdown = test::render("fn a() { }");
|
||||
assert !str::contains(markdown, "Return value");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_blank_line_after_return_description() {
|
||||
let markdown = test::render(
|
||||
"#[doc(return = \"blorp\")] fn a() -> int { }"
|
||||
);
|
||||
assert str::contains(markdown, "blorp\n\n");
|
||||
}
|
||||
|
||||
fn write_failure(ctxt: ctxt, str: option<str>) {
|
||||
alt str {
|
||||
some(str) {
|
||||
write_lead(ctxt, "Failure conditions");
|
||||
ctxt.w.write_line(str);
|
||||
ctxt.w.write_line("");
|
||||
}
|
||||
none { }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_failure_conditions() {
|
||||
let markdown = test::render(
|
||||
"#[doc(failure = \"it's the fail\")] fn a () { }");
|
||||
assert str::contains(
|
||||
markdown,
|
||||
"\n\n__Failure conditions__: it's the fail\n\n");
|
||||
assert str::contains(markdown, "Function `a`\n\n fn a()");
|
||||
}
|
||||
|
||||
fn write_const(
|
||||
@ -601,9 +468,8 @@ fn write_const(
|
||||
doc: doc::constdoc
|
||||
) {
|
||||
write_header(ctxt, h2, doc::consttag(doc));
|
||||
write_sig(ctxt, doc.ty);
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_sig(ctxt, doc.sig);
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -615,9 +481,9 @@ fn should_write_const_header() {
|
||||
#[test]
|
||||
fn should_write_const_description() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"a\", desc = \"b\")]\
|
||||
"#[doc = \"b\"]\
|
||||
const a: bool = true;");
|
||||
assert str::contains(markdown, "\n\na\n\nb\n\n");
|
||||
assert str::contains(markdown, "\n\nb\n\n");
|
||||
}
|
||||
|
||||
fn write_enum(
|
||||
@ -625,8 +491,7 @@ fn write_enum(
|
||||
doc: doc::enumdoc
|
||||
) {
|
||||
write_header(ctxt, h2, doc::enumtag(doc));
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
write_variants(ctxt, doc.variants);
|
||||
}
|
||||
|
||||
@ -639,8 +504,8 @@ fn should_write_enum_header() {
|
||||
#[test]
|
||||
fn should_write_enum_description() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"a\", desc = \"b\")] enum a { b }");
|
||||
assert str::contains(markdown, "\n\na\n\nb\n\n");
|
||||
"#[doc = \"b\"] enum a { b }");
|
||||
assert str::contains(markdown, "\n\nb\n\n");
|
||||
}
|
||||
|
||||
fn write_variants(
|
||||
@ -651,8 +516,7 @@ fn write_variants(
|
||||
ret;
|
||||
}
|
||||
|
||||
ctxt.w.write_line("Variants:");
|
||||
ctxt.w.write_line("");
|
||||
write_header_(ctxt, h4, "Variants");
|
||||
|
||||
vec::iter(docs, {|variant| write_variant(ctxt, variant) });
|
||||
|
||||
@ -680,7 +544,7 @@ fn should_write_variant_list() {
|
||||
#[doc = \"test\"] c }");
|
||||
assert str::contains(
|
||||
markdown,
|
||||
"\n\nVariants:\n\
|
||||
"\n\n#### Variants\n\
|
||||
\n* `b` - test\
|
||||
\n* `c` - test\n\n");
|
||||
}
|
||||
@ -690,7 +554,7 @@ fn should_write_variant_list_without_descs() {
|
||||
let markdown = test::render("enum a { b, c }");
|
||||
assert str::contains(
|
||||
markdown,
|
||||
"\n\nVariants:\n\
|
||||
"\n\n#### Variants\n\
|
||||
\n* `b`\
|
||||
\n* `c`\n\n");
|
||||
}
|
||||
@ -700,7 +564,7 @@ fn should_write_variant_list_with_signatures() {
|
||||
let markdown = test::render("enum a { b(int), #[doc = \"a\"] c(int) }");
|
||||
assert str::contains(
|
||||
markdown,
|
||||
"\n\nVariants:\n\
|
||||
"\n\n#### Variants\n\
|
||||
\n* `b(int)`\
|
||||
\n* `c(int)` - a\n\n");
|
||||
}
|
||||
@ -708,9 +572,7 @@ fn should_write_variant_list_with_signatures() {
|
||||
fn write_res(ctxt: ctxt, doc: doc::resdoc) {
|
||||
write_header(ctxt, h2, doc::restag(doc));
|
||||
write_sig(ctxt, doc.sig);
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_args(ctxt, doc.args);
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -725,17 +587,9 @@ fn should_write_resource_signature() {
|
||||
assert str::contains(markdown, "\n resource r(a: bool)\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_resource_args() {
|
||||
let markdown = test::render("#[doc(args(a = \"b\"))]\
|
||||
resource r(a: bool) { }");
|
||||
assert str::contains(markdown, "__Arguments__: \n\n* `a` - b");
|
||||
}
|
||||
|
||||
fn write_iface(ctxt: ctxt, doc: doc::ifacedoc) {
|
||||
write_header(ctxt, h2, doc::ifacetag(doc));
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
write_methods(ctxt, doc.methods);
|
||||
}
|
||||
|
||||
@ -748,11 +602,8 @@ fn write_method(ctxt: ctxt, doc: doc::methoddoc) {
|
||||
write_fnlike(
|
||||
ctxt,
|
||||
doc.sig,
|
||||
doc.brief,
|
||||
doc.desc,
|
||||
doc.args,
|
||||
doc.return,
|
||||
doc.failure
|
||||
doc.sections
|
||||
);
|
||||
}
|
||||
|
||||
@ -762,17 +613,10 @@ fn should_write_iface_header() {
|
||||
assert str::contains(markdown, "## Interface `i`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_brief() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"brief\")] iface i { fn a(); }");
|
||||
assert str::contains(markdown, "brief");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] iface i { fn a(); }");
|
||||
"#[doc = \"desc\"] iface i { fn a(); }");
|
||||
assert str::contains(markdown, "desc");
|
||||
}
|
||||
|
||||
@ -790,45 +634,9 @@ fn should_write_iface_method_signature() {
|
||||
assert str::contains(markdown, "\n fn a()");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_method_argument_header() {
|
||||
let markdown = test::render(
|
||||
"iface a { fn a(b: int); }");
|
||||
assert str::contains(markdown, "\n\n__Arguments__: \n\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_method_arguments() {
|
||||
let markdown = test::render(
|
||||
"iface a { fn a(b: int); }");
|
||||
assert str::contains(markdown, "* `b`\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_write_iface_method_arguments_if_none() {
|
||||
let markdown = test::render(
|
||||
"iface a { fn a(); }");
|
||||
assert !str::contains(markdown, "Arguments");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_method_return_info() {
|
||||
let markdown = test::render(
|
||||
"iface a { #[doc(return = \"test\")] fn a() -> int; }");
|
||||
assert str::contains(markdown, "__Return value__: test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_iface_method_failure_conditions() {
|
||||
let markdown = test::render(
|
||||
"iface a { #[doc(failure = \"nuked\")] fn a(); }");
|
||||
assert str::contains(markdown, "__Failure conditions__: nuked");
|
||||
}
|
||||
|
||||
fn write_impl(ctxt: ctxt, doc: doc::impldoc) {
|
||||
write_header(ctxt, h2, doc::impltag(doc));
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
write_methods(ctxt, doc.methods);
|
||||
}
|
||||
|
||||
@ -844,17 +652,10 @@ fn should_write_impl_header_with_iface() {
|
||||
assert str::contains(markdown, "## Implementation `i of j for int`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_brief() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"brief\")] impl i for int { fn a() { } }");
|
||||
assert str::contains(markdown, "brief");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] impl i for int { fn a() { } }");
|
||||
"#[doc = \"desc\"] impl i for int { fn a() { } }");
|
||||
assert str::contains(markdown, "desc");
|
||||
}
|
||||
|
||||
@ -872,49 +673,13 @@ fn should_write_impl_method_signature() {
|
||||
assert str::contains(markdown, "\n fn a()");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_method_argument_header() {
|
||||
let markdown = test::render(
|
||||
"impl a for int { fn a(b: int) { } }");
|
||||
assert str::contains(markdown, "\n\n__Arguments__: \n\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_method_arguments() {
|
||||
let markdown = test::render(
|
||||
"impl a for int { fn a(b: int) { } }");
|
||||
assert str::contains(markdown, "* `b`\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_write_impl_method_arguments_if_none() {
|
||||
let markdown = test::render(
|
||||
"impl a for int { fn a() { } }");
|
||||
assert !str::contains(markdown, "Arguments");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_method_return_info() {
|
||||
let markdown = test::render(
|
||||
"impl a for int { #[doc(return = \"test\")] fn a() -> int { } }");
|
||||
assert str::contains(markdown, "__Return value__: test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_impl_method_failure_conditions() {
|
||||
let markdown = test::render(
|
||||
"impl a for int { #[doc(failure = \"nuked\")] fn a() { } }");
|
||||
assert str::contains(markdown, "__Failure conditions__: nuked");
|
||||
}
|
||||
|
||||
fn write_type(
|
||||
ctxt: ctxt,
|
||||
doc: doc::tydoc
|
||||
) {
|
||||
write_header(ctxt, h2, doc::tytag(doc));
|
||||
write_sig(ctxt, doc.sig);
|
||||
write_brief(ctxt, doc.brief());
|
||||
write_desc(ctxt, doc.desc());
|
||||
write_common(ctxt, doc.desc(), doc.sections());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -923,17 +688,10 @@ fn should_write_type_header() {
|
||||
assert str::contains(markdown, "## Type `t`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_type_brief() {
|
||||
let markdown = test::render(
|
||||
"#[doc(brief = \"brief\")] type t = int;");
|
||||
assert str::contains(markdown, "\n\nbrief\n\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_write_type_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] type t = int;");
|
||||
"#[doc = \"desc\"] type t = int;");
|
||||
assert str::contains(markdown, "\n\ndesc\n\n");
|
||||
}
|
||||
|
||||
@ -968,6 +726,14 @@ mod test {
|
||||
#debug("doc (path): %?", doc);
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (attr): %?", doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (desc_to_brief): %?", doc);
|
||||
let doc = unindent_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (unindent): %?", doc);
|
||||
let doc = sectionalize_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (trim): %?", doc);
|
||||
let doc = trim_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (sectionalize): %?", doc);
|
||||
let doc = markdown_index_pass::mk_pass(config).f(srv, doc);
|
||||
#debug("doc (index): %?", doc);
|
||||
(srv, doc)
|
||||
|
@ -1,129 +0,0 @@
|
||||
#[doc = "Prunes args, retvals of the document tree that \
|
||||
contain no documentation"];
|
||||
|
||||
export mk_pass;
|
||||
|
||||
fn mk_pass() -> pass {
|
||||
{
|
||||
name: "prune_undoc_details",
|
||||
f: run
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
_srv: astsrv::srv,
|
||||
doc: doc::doc
|
||||
) -> doc::doc {
|
||||
let fold = fold::fold({
|
||||
fold_fn: fold_fn,
|
||||
fold_res: fold_res,
|
||||
fold_iface: fold_iface,
|
||||
fold_impl: fold_impl
|
||||
with *fold::default_any_fold(())
|
||||
});
|
||||
fold.fold_doc(fold, doc)
|
||||
}
|
||||
|
||||
fn fold_fn(
|
||||
fold: fold::fold<()>,
|
||||
doc: doc::fndoc
|
||||
) -> doc::fndoc {
|
||||
let doc = fold::default_seq_fold_fn(fold, doc);
|
||||
|
||||
{
|
||||
args: prune_args(doc.args)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
|
||||
vec::filter_map(docs) {|doc|
|
||||
if option::is_some(doc.desc) {
|
||||
some(doc)
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_arguments() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
|
||||
assert vec::is_empty(doc.cratemod().fns()[0].args);
|
||||
}
|
||||
|
||||
fn fold_res(
|
||||
fold: fold::fold<()>,
|
||||
doc: doc::resdoc
|
||||
) -> doc::resdoc {
|
||||
let doc = fold::default_seq_fold_res(fold, doc);
|
||||
|
||||
{
|
||||
args: prune_args(doc.args)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_resource_args() {
|
||||
let doc = test::mk_doc("#[doc = \"drunk\"]\
|
||||
resource r(a: bool) { }");
|
||||
assert vec::is_empty(doc.cratemod().resources()[0].args);
|
||||
}
|
||||
|
||||
fn fold_iface(
|
||||
fold: fold::fold<()>,
|
||||
doc: doc::ifacedoc
|
||||
) -> doc::ifacedoc {
|
||||
let doc = fold::default_seq_fold_iface(fold, doc);
|
||||
|
||||
{
|
||||
methods: prune_methods(doc.methods)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
|
||||
par::anymap(docs) {|doc|
|
||||
{
|
||||
args: prune_args(doc.args)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_iface_method_args() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
|
||||
assert vec::is_empty(doc.cratemod().ifaces()[0].methods[0].args);
|
||||
}
|
||||
|
||||
fn fold_impl(
|
||||
fold: fold::fold<()>,
|
||||
doc: doc::impldoc
|
||||
) -> doc::impldoc {
|
||||
let doc = fold::default_seq_fold_impl(fold, doc);
|
||||
|
||||
{
|
||||
methods: prune_methods(doc.methods)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_impl_method_args() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"hey\"] impl i for int { fn a(b: bool) { } }");
|
||||
assert vec::is_empty(doc.cratemod().impls()[0].methods[0].args);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
run(srv, doc)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,377 +0,0 @@
|
||||
#[doc = "Prunes items of the document tree that contain no documentation"];
|
||||
|
||||
export mk_pass;
|
||||
|
||||
fn mk_pass() -> pass {
|
||||
{
|
||||
name: "prune_undoc_items",
|
||||
f: run
|
||||
}
|
||||
}
|
||||
|
||||
type ctxt = {
|
||||
mutable have_docs: bool
|
||||
};
|
||||
|
||||
fn run(
|
||||
_srv: astsrv::srv,
|
||||
doc: doc::doc
|
||||
) -> doc::doc {
|
||||
let ctxt = {
|
||||
mutable have_docs: true
|
||||
};
|
||||
let fold = fold::fold({
|
||||
fold_mod: fold_mod,
|
||||
fold_fn: fold_fn,
|
||||
fold_const: fold_const,
|
||||
fold_enum: fold_enum,
|
||||
fold_res: fold_res,
|
||||
fold_iface: fold_iface,
|
||||
fold_impl: fold_impl,
|
||||
fold_type: fold_type
|
||||
with *fold::default_any_fold(ctxt)
|
||||
});
|
||||
fold.fold_doc(fold, doc)
|
||||
}
|
||||
|
||||
fn fold_mod(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::moddoc
|
||||
) -> doc::moddoc {
|
||||
let doc = {
|
||||
items: vec::filter_map(doc.items) {|itemtag|
|
||||
alt itemtag {
|
||||
doc::modtag(moddoc) {
|
||||
let doc = fold.fold_mod(fold, moddoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::modtag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::fntag(fndoc) {
|
||||
let doc = fold.fold_fn(fold, fndoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::fntag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::consttag(constdoc) {
|
||||
let doc = fold.fold_const(fold, constdoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::consttag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::enumtag(enumdoc) {
|
||||
let doc = fold.fold_enum(fold, enumdoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::enumtag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::restag(resdoc) {
|
||||
let doc = fold.fold_res(fold, resdoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::restag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::ifacetag(ifacedoc) {
|
||||
let doc = fold.fold_iface(fold, ifacedoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::ifacetag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::impltag(impldoc) {
|
||||
let doc = fold.fold_impl(fold, impldoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::impltag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
doc::tytag(tydoc) {
|
||||
let doc = fold.fold_type(fold, tydoc);
|
||||
if fold.ctxt.have_docs {
|
||||
some(doc::tytag(doc))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
_ { some(itemtag) }
|
||||
}
|
||||
}
|
||||
with fold::default_any_fold_mod(fold, doc)
|
||||
};
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| vec::is_not_empty(doc.items);
|
||||
ret doc;
|
||||
}
|
||||
|
||||
fn fold_fn(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::fndoc
|
||||
) -> doc::fndoc {
|
||||
let doc = fold::default_seq_fold_fn(fold, doc);
|
||||
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| args_have_docs(doc.args)
|
||||
|| doc.return.desc != none
|
||||
|| doc.failure != none;
|
||||
ret doc;
|
||||
}
|
||||
|
||||
fn args_have_docs(docs: [doc::argdoc]) -> bool {
|
||||
vec::foldl(false, docs) {|accum, doc|
|
||||
accum || doc.desc != none
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_fns_with_undocumented_arguments() {
|
||||
let doc = test::mk_doc("fn a(a: int) { }");
|
||||
assert vec::is_empty(doc.cratemod().fns());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_fns_with_documented_arguments() {
|
||||
let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn a(a: int) { }");
|
||||
assert vec::is_not_empty(doc.cratemod().fns());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_fns_with_documented_failure_conditions() {
|
||||
let doc = test::mk_doc("#[doc(failure = \"yup\")] fn a() { }");
|
||||
assert vec::is_not_empty(doc.cratemod().fns());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_mods() {
|
||||
let doc = test::mk_doc("mod a { }");
|
||||
assert vec::is_empty(doc.cratemod().mods());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_undocument_mods_with_documented_mods() {
|
||||
let doc = test::mk_doc("mod a { #[doc = \"b\"] mod b { } }");
|
||||
assert vec::is_not_empty(doc.cratemod().mods());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_undocument_mods_with_documented_fns() {
|
||||
let doc = test::mk_doc("mod a { #[doc = \"b\"] fn b() { } }");
|
||||
assert vec::is_not_empty(doc.cratemod().mods());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_fns() {
|
||||
let doc = test::mk_doc("fn a() { }");
|
||||
assert vec::is_empty(doc.cratemod().fns());
|
||||
}
|
||||
|
||||
fn fold_const(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::constdoc
|
||||
) -> doc::constdoc {
|
||||
let doc = fold::default_seq_fold_const(fold, doc);
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none;
|
||||
ret doc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_consts() {
|
||||
let doc = test::mk_doc("const a: bool = true;");
|
||||
assert vec::is_empty(doc.cratemod().consts());
|
||||
}
|
||||
|
||||
fn fold_enum(fold: fold::fold<ctxt>, doc: doc::enumdoc) -> doc::enumdoc {
|
||||
let doc = {
|
||||
variants: vec::filter_map(doc.variants) {|variant|
|
||||
if variant.desc != none {
|
||||
some(variant)
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
with fold::default_seq_fold_enum(fold, doc)
|
||||
};
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| vec::is_not_empty(doc.variants);
|
||||
ret doc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_enums() {
|
||||
let doc = test::mk_doc("enum a { b }");
|
||||
assert vec::is_empty(doc.cratemod().enums());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_variants() {
|
||||
let doc = test::mk_doc("#[doc = \"a\"] enum a { b }");
|
||||
assert vec::is_empty(doc.cratemod().enums()[0].variants);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_enums_with_documented_variants() {
|
||||
let doc = test::mk_doc("enum a { #[doc = \"a\"] b }");
|
||||
assert vec::is_not_empty(doc.cratemod().enums());
|
||||
}
|
||||
|
||||
fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
|
||||
let doc = fold::default_seq_fold_res(fold, doc);
|
||||
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| args_have_docs(doc.args);
|
||||
ret doc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_resources() {
|
||||
let doc = test::mk_doc("resource r(a: bool) { }");
|
||||
assert vec::is_empty(doc.cratemod().resources());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_resources_with_documented_args() {
|
||||
let doc = test::mk_doc("#[doc(args(a = \"drunk\"))]\
|
||||
resource r(a: bool) { }");
|
||||
assert vec::is_not_empty(doc.cratemod().resources());
|
||||
}
|
||||
|
||||
fn fold_iface(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::ifacedoc
|
||||
) -> doc::ifacedoc {
|
||||
let doc = fold::default_seq_fold_iface(fold, doc);
|
||||
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| methods_have_docs(doc.methods);
|
||||
ret doc;
|
||||
}
|
||||
|
||||
fn methods_have_docs(docs: [doc::methoddoc]) -> bool {
|
||||
vec::foldl(false, docs) {|accum, doc|
|
||||
accum
|
||||
|| doc.brief != none
|
||||
|| doc.desc != none
|
||||
|| args_have_docs(doc.args)
|
||||
|| doc.return.desc != none
|
||||
|| doc.failure != none
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_ifaces() {
|
||||
let doc = test::mk_doc("iface i { fn a(); }");
|
||||
assert vec::is_empty(doc.cratemod().ifaces());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_documented_ifaces() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
|
||||
assert vec::is_not_empty(doc.cratemod().ifaces());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_ifaces_with_undocumented_args() {
|
||||
let doc = test::mk_doc("iface i { fn a(b: bool); }");
|
||||
assert vec::is_empty(doc.cratemod().ifaces());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_ifaces_with_documented_methods() {
|
||||
let doc = test::mk_doc("iface i { #[doc = \"hey\"] fn a(); }");
|
||||
assert vec::is_not_empty(doc.cratemod().ifaces());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_undocumented_iface_methods() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
|
||||
assert vec::is_not_empty(doc.cratemod().ifaces()[0].methods);
|
||||
}
|
||||
|
||||
fn fold_impl(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::impldoc
|
||||
) -> doc::impldoc {
|
||||
let doc = fold::default_seq_fold_impl(fold, doc);
|
||||
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none
|
||||
|| methods_have_docs(doc.methods);
|
||||
ret doc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_impls() {
|
||||
let doc = test::mk_doc("impl i for int { fn a() { } }");
|
||||
assert vec::is_empty(doc.cratemod().impls());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_documented_impls() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] impl i for int { fn a() { } }");
|
||||
assert vec::is_not_empty(doc.cratemod().impls());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_impls_with_documented_methods() {
|
||||
let doc = test::mk_doc("impl i for int { #[doc = \"hey\"] fn a() { } }");
|
||||
assert vec::is_not_empty(doc.cratemod().impls());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_elide_undocumented_impl_methods() {
|
||||
let doc = test::mk_doc("#[doc = \"hey\"] impl i for int { fn a() { } }");
|
||||
assert vec::is_not_empty(doc.cratemod().impls()[0].methods);
|
||||
}
|
||||
|
||||
fn fold_type(
|
||||
fold: fold::fold<ctxt>,
|
||||
doc: doc::tydoc
|
||||
) -> doc::tydoc {
|
||||
let doc = fold::default_seq_fold_type(fold, doc);
|
||||
|
||||
fold.ctxt.have_docs =
|
||||
doc.brief() != none
|
||||
|| doc.desc() != none;
|
||||
ret doc;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_elide_undocumented_types() {
|
||||
let doc = test::mk_doc("type t = int;");
|
||||
assert vec::is_empty(doc.cratemod().types());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
run(srv, doc)
|
||||
}
|
||||
}
|
||||
}
|
@ -24,8 +24,6 @@ mod fold;
|
||||
mod path_pass;
|
||||
mod attr_pass;
|
||||
mod tystr_pass;
|
||||
mod prune_undoc_details_pass;
|
||||
mod prune_undoc_items_pass;
|
||||
mod prune_unexported_pass;
|
||||
mod prune_hidden_pass;
|
||||
mod desc_to_brief_pass;
|
||||
@ -40,3 +38,4 @@ mod sort_item_type_pass;
|
||||
mod reexport_pass;
|
||||
mod par;
|
||||
mod page_pass;
|
||||
mod sectionalize_pass;
|
@ -143,13 +143,11 @@ fn run(config: config::config) {
|
||||
tystr_pass::mk_pass(),
|
||||
path_pass::mk_pass(),
|
||||
attr_pass::mk_pass(),
|
||||
prune_undoc_details_pass::mk_pass(),
|
||||
// FIXME: This pass should be optional
|
||||
// prune_undoc_items_pass::mk_pass(),
|
||||
prune_hidden_pass::mk_pass(),
|
||||
desc_to_brief_pass::mk_pass(),
|
||||
trim_pass::mk_pass(),
|
||||
unindent_pass::mk_pass(),
|
||||
sectionalize_pass::mk_pass(),
|
||||
trim_pass::mk_pass(),
|
||||
sort_item_name_pass::mk_pass(),
|
||||
sort_item_type_pass::mk_pass(),
|
||||
markdown_index_pass::mk_pass(config),
|
||||
|
237
src/rustdoc/sectionalize_pass.rs
Normal file
237
src/rustdoc/sectionalize_pass.rs
Normal file
@ -0,0 +1,237 @@
|
||||
#[doc = "Breaks rustdocs into sections according to their headers"];
|
||||
|
||||
export mk_pass;
|
||||
|
||||
fn mk_pass() -> pass {
|
||||
{
|
||||
name: "sectionalize",
|
||||
f: run
|
||||
}
|
||||
}
|
||||
|
||||
fn run(_srv: astsrv::srv, doc: doc::doc) -> doc::doc {
|
||||
let fold = fold::fold({
|
||||
fold_item: fold_item,
|
||||
fold_iface: fold_iface,
|
||||
fold_impl: fold_impl
|
||||
with *fold::default_any_fold(())
|
||||
});
|
||||
fold.fold_doc(fold, doc)
|
||||
}
|
||||
|
||||
fn fold_item(fold: fold::fold<()>, doc: doc::itemdoc) -> doc::itemdoc {
|
||||
let doc = fold::default_seq_fold_item(fold, doc);
|
||||
let (desc, sections) = sectionalize(doc.desc);
|
||||
|
||||
{
|
||||
desc: desc,
|
||||
sections: sections
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_iface(fold: fold::fold<()>, doc: doc::ifacedoc) -> doc::ifacedoc {
|
||||
let doc = fold::default_seq_fold_iface(fold, doc);
|
||||
|
||||
{
|
||||
methods: par::anymap(doc.methods) {|method|
|
||||
let (desc, sections) = sectionalize(method.desc);
|
||||
|
||||
{
|
||||
desc: desc,
|
||||
sections: sections
|
||||
with method
|
||||
}
|
||||
}
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
|
||||
let doc = fold::default_seq_fold_impl(fold, doc);
|
||||
|
||||
{
|
||||
methods: par::anymap(doc.methods) {|method|
|
||||
let (desc, sections) = sectionalize(method.desc);
|
||||
|
||||
{
|
||||
desc: desc,
|
||||
sections: sections
|
||||
with method
|
||||
}
|
||||
}
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn sectionalize(desc: option<str>) -> (option<str>, [doc::section]) {
|
||||
|
||||
#[doc = "
|
||||
|
||||
Take a description of the form
|
||||
|
||||
General text
|
||||
|
||||
# Section header
|
||||
|
||||
Section text
|
||||
|
||||
# Section header
|
||||
|
||||
Section text
|
||||
|
||||
and remove each header and accompanying text into section records.
|
||||
|
||||
"];
|
||||
|
||||
if option::is_none(desc) {
|
||||
ret (none, []);
|
||||
}
|
||||
|
||||
let lines = str::lines(option::get(desc));
|
||||
|
||||
let new_desc = none;
|
||||
let current_section = none;
|
||||
let sections = [];
|
||||
|
||||
for line in lines {
|
||||
alt parse_header(line) {
|
||||
some(header) {
|
||||
if option::is_some(current_section) {
|
||||
sections += [option::get(current_section)];
|
||||
}
|
||||
current_section = some({
|
||||
header: header,
|
||||
body: ""
|
||||
});
|
||||
}
|
||||
none {
|
||||
alt current_section {
|
||||
some(section) {
|
||||
current_section = some({
|
||||
body: section.body + "\n" + line
|
||||
with section
|
||||
});
|
||||
}
|
||||
none {
|
||||
alt new_desc {
|
||||
some(desc) {
|
||||
new_desc = some(desc + "\n" + line);
|
||||
}
|
||||
none {
|
||||
new_desc = some(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if option::is_some(current_section) {
|
||||
sections += [option::get(current_section)];
|
||||
}
|
||||
|
||||
(new_desc, sections)
|
||||
}
|
||||
|
||||
fn parse_header(line: str) -> option<str> {
|
||||
if str::starts_with(line, "# ") {
|
||||
some(str::slice(line, 2u, str::len(line)))
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_create_section_headers() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
mod a { }");
|
||||
assert str::contains(
|
||||
doc.cratemod().mods()[0].item.sections[0].header,
|
||||
"Header");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_create_section_bodies() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
mod a { }");
|
||||
assert str::contains(
|
||||
doc.cratemod().mods()[0].item.sections[0].body,
|
||||
"Body");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_create_sections_from_indented_headers() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\n\
|
||||
Text\n # Header\n\
|
||||
Body\"]\
|
||||
mod a { }");
|
||||
assert vec::is_empty(doc.cratemod().mods()[0].item.sections);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_remove_section_text_from_main_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
Description\n\n\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
mod a { }");
|
||||
assert !str::contains(
|
||||
option::get(doc.cratemod().mods()[0].desc()),
|
||||
"Header");
|
||||
assert !str::contains(
|
||||
option::get(doc.cratemod().mods()[0].desc()),
|
||||
"Body");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_eliminate_desc_if_it_is_just_whitespace() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
mod a { }");
|
||||
assert doc.cratemod().mods()[0].desc() == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_sectionalize_iface_methods() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i {
|
||||
#[doc = \"\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].sections.len() == 1u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_sectionalize_impl_methods() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for bool {
|
||||
#[doc = \"\
|
||||
# Header\n\
|
||||
Body\"]\
|
||||
fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].sections.len() == 1u;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
run(srv, doc)
|
||||
}
|
||||
}
|
||||
}
|
@ -20,9 +20,7 @@ fn run(
|
||||
) -> doc::doc {
|
||||
let fold = fold::fold({
|
||||
fold_item: fold_item,
|
||||
fold_fn: fold_fn,
|
||||
fold_enum: fold_enum,
|
||||
fold_res: fold_res,
|
||||
fold_iface: fold_iface,
|
||||
fold_impl: fold_impl
|
||||
with *fold::default_any_fold(op)
|
||||
@ -39,28 +37,18 @@ fn fold_item(fold: fold::fold<op>, doc: doc::itemdoc) -> doc::itemdoc {
|
||||
|
||||
{
|
||||
brief: maybe_apply_op(fold.ctxt, doc.brief),
|
||||
desc: maybe_apply_op(fold.ctxt, doc.desc)
|
||||
desc: maybe_apply_op(fold.ctxt, doc.desc),
|
||||
sections: apply_to_sections(fold.ctxt, doc.sections)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_fn(fold: fold::fold<op>, doc: doc::fndoc) -> doc::fndoc {
|
||||
let fold_ctxt = fold.ctxt;
|
||||
let doc = fold::default_seq_fold_fn(fold, doc);
|
||||
|
||||
{
|
||||
args: par::anymap(doc.args) {|doc|
|
||||
{
|
||||
desc: maybe_apply_op(fold_ctxt, doc.desc)
|
||||
with doc
|
||||
}
|
||||
},
|
||||
return: {
|
||||
desc: maybe_apply_op(fold.ctxt, doc.return.desc)
|
||||
with doc.return
|
||||
},
|
||||
failure: maybe_apply_op(fold.ctxt, doc.failure)
|
||||
with doc
|
||||
fn apply_to_sections(op: op, sections: [doc::section]) -> [doc::section] {
|
||||
par::anymap(sections) {|section|
|
||||
{
|
||||
header: op(section.header),
|
||||
body: op(section.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,21 +67,6 @@ fn fold_enum(fold: fold::fold<op>, doc: doc::enumdoc) -> doc::enumdoc {
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_res(fold: fold::fold<op>, doc: doc::resdoc) -> doc::resdoc {
|
||||
let fold_ctxt = fold.ctxt;
|
||||
let doc = fold::default_seq_fold_res(fold, doc);
|
||||
|
||||
{
|
||||
args: par::anymap(doc.args) {|arg|
|
||||
{
|
||||
desc: maybe_apply_op(fold_ctxt, arg.desc)
|
||||
with arg
|
||||
}
|
||||
}
|
||||
with doc
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_iface(fold: fold::fold<op>, doc: doc::ifacedoc) -> doc::ifacedoc {
|
||||
let doc = fold::default_seq_fold_iface(fold, doc);
|
||||
|
||||
@ -108,17 +81,7 @@ fn apply_to_methods(op: op, docs: [doc::methoddoc]) -> [doc::methoddoc] {
|
||||
{
|
||||
brief: maybe_apply_op(op, doc.brief),
|
||||
desc: maybe_apply_op(op, doc.desc),
|
||||
args: par::anymap(doc.args) {|doc|
|
||||
{
|
||||
desc: maybe_apply_op(op, doc.desc)
|
||||
with doc
|
||||
}
|
||||
},
|
||||
return: {
|
||||
desc: maybe_apply_op(op, doc.return.desc)
|
||||
with doc.return
|
||||
},
|
||||
failure: maybe_apply_op(op, doc.failure)
|
||||
sections: apply_to_sections(op, doc.sections)
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -135,13 +98,13 @@ fn fold_impl(fold: fold::fold<op>, doc: doc::impldoc) -> doc::impldoc {
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_enum_brief() {
|
||||
let doc = test::mk_doc("#[doc(brief = \" a \")] enum a { b }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] enum a { b }");
|
||||
assert doc.cratemod().enums()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_enum_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \" a \")] enum a { b }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] enum a { b }");
|
||||
assert doc.cratemod().enums()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
@ -153,141 +116,160 @@ fn should_execute_op_on_variant_desc() {
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_resource_brief() {
|
||||
let doc = test::mk_doc("#[doc(brief = \" a \")] resource r(a: bool) { }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_resource_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \" a \")] resource r(a: bool) { }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_resource_args() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(args(a = \" a \"))] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].args[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] iface i { fn a(); }");
|
||||
"#[doc = \" a \"] iface i { fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] iface i { fn a(); }");
|
||||
"#[doc = \" a \"] iface i { fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(brief = \" a \")] fn a(); }");
|
||||
"iface i { #[doc = \" a \"] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].brief == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(desc = \" a \")] fn a(); }");
|
||||
"iface i { #[doc = \" a \"] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_args() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(args(a = \" a \"))] fn a(a: bool); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].args[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_return() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(return = \" a \")] fn a() -> int; }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].return.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_failure_condition() {
|
||||
let doc = test::mk_doc("iface i { #[doc(failure = \" a \")] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].failure == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] impl i for int { fn a() { } }");
|
||||
"#[doc = \" a \"] impl i for int { fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] impl i for int { fn a() { } }");
|
||||
"#[doc = \" a \"] impl i for int { fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(brief = \" a \")] fn a() { } }");
|
||||
"impl i for int { #[doc = \" a \"] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].brief == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(desc = \" a \")] fn a() { } }");
|
||||
"impl i for int { #[doc = \" a \"] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_args() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(args(a = \" a \"))] fn a(a: bool) { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].args[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_return() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(return = \" a \")] fn a() -> int { fail } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].return.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_failure_condition() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(failure = \" a \")] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].failure == some("a");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_type_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] type t = int;");
|
||||
"#[doc = \" a \"] type t = int;");
|
||||
assert doc.cratemod().types()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_type_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] type t = int;");
|
||||
"#[doc = \" a \"] type t = int;");
|
||||
assert doc.cratemod().types()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_item_section_headers() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
# Header \n\
|
||||
Body\"]\
|
||||
fn a() { }");
|
||||
assert doc.cratemod().fns()[0].sections()[0].header == "Header";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_item_section_bodies() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc = \"\
|
||||
# Header\n\
|
||||
Body \"]\
|
||||
fn a() { }");
|
||||
assert doc.cratemod().fns()[0].sections()[0].body == "Body";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_iface_method_section_headers() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i {
|
||||
#[doc = \"\
|
||||
# Header \n\
|
||||
Body\"]\
|
||||
fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].sections[0].header
|
||||
== "Header";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_iface_method_section_bodies() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i {
|
||||
#[doc = \"\
|
||||
# Header\n\
|
||||
Body \"]\
|
||||
fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].sections[0].body == "Body";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_impl_method_section_headers() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for bool {
|
||||
#[doc = \"\
|
||||
# Header \n\
|
||||
Body\"]\
|
||||
fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].sections[0].header
|
||||
== "Header";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_on_impl_method_section_bodies() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for bool {
|
||||
#[doc = \"\
|
||||
# Header\n\
|
||||
Body \"]\
|
||||
fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].sections[0].body == "Body";
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
let doc = sectionalize_pass::mk_pass().f(srv, doc);
|
||||
mk_pass("", {|s| str::trim(s)}).f(srv, doc)
|
||||
}
|
||||
}
|
||||
|
@ -14,50 +14,12 @@ fn mk_pass() -> pass {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_mod() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
fn should_trim_text() {
|
||||
let doc = test::mk_doc("#[doc = \" desc \"] \
|
||||
mod m { }");
|
||||
assert doc.cratemod().mods()[0].brief() == some("brief");
|
||||
assert doc.cratemod().mods()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_const() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].brief() == some("brief");
|
||||
assert doc.cratemod().consts()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_fn() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
fn a() { }");
|
||||
assert doc.cratemod().fns()[0].brief() == some("brief");
|
||||
assert doc.cratemod().fns()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_args() {
|
||||
let doc = test::mk_doc("#[doc(args(a = \"\na\n\"))] fn a(a: int) { }");
|
||||
assert doc.cratemod().fns()[0].args[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_ret() {
|
||||
let doc = test::mk_doc("#[doc(return = \"\na\n\")] fn a() -> int { }");
|
||||
assert doc.cratemod().fns()[0].return.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_failure_conditions() {
|
||||
let doc = test::mk_doc("#[doc(failure = \"\na\n\")] fn a() -> int { }");
|
||||
assert doc.cratemod().fns()[0].failure == some("a");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
|
@ -81,7 +81,7 @@ fn fold_const(
|
||||
let srv = fold.ctxt;
|
||||
|
||||
{
|
||||
ty: some(astsrv::exec(srv) {|ctxt|
|
||||
sig: some(astsrv::exec(srv) {|ctxt|
|
||||
alt check ctxt.ast_map.get(doc.id()) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_const(ty, _), _
|
||||
@ -97,7 +97,7 @@ fn fold_const(
|
||||
#[test]
|
||||
fn should_add_const_types() {
|
||||
let doc = test::mk_doc("const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].ty == some("bool");
|
||||
assert doc.cratemod().consts()[0].sig == some("bool");
|
||||
}
|
||||
|
||||
fn fold_enum(
|
||||
|
Loading…
Reference in New Issue
Block a user