Merge branch 'master' into register-snapshots

This commit is contained in:
Tim Chevalier 2012-01-31 21:08:53 -08:00
commit e204aa281d
15 changed files with 1018 additions and 544 deletions

View File

@ -30,7 +30,7 @@ This behavior can be disabled with the `no_core` crate attribute."
export box, char, float, bessel, f32, f64, int, str, ptr;
export uint, u8, u32, u64, vec, bool;
export either, option, result;
export either, option, result, iter;
export ctypes, sys, unsafe, comm, task, logging;
export extfmt;
export math;
@ -64,7 +64,7 @@ mod either;
mod option;
mod result;
mod tuple;
mod iter;
// Runtime and language-primitive support

171
src/libcore/iter.rs Normal file
View File

@ -0,0 +1,171 @@
iface iterable<A> {
fn iter(blk: fn(A));
}
impl<A> of iterable<A> for fn@(fn(A)) {
fn iter(blk: fn(A)) {
self(blk);
}
}
// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
fn iter(blk: fn(&&int)) {
self {|i| blk(i)}
}
}
impl of iterable<uint> for fn@(fn(uint)) {
fn iter(blk: fn(&&uint)) {
self {|i| blk(i)}
}
}
impl<A> of iterable<A> for [A] {
fn iter(blk: fn(A)) {
vec::iter(self, blk)
}
}
impl<A> of iterable<A> for option<A> {
fn iter(blk: fn(A)) {
option::may(self, blk)
}
}
fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
let i = 0u;
self.iter {|a|
blk(i, a);
i += 1u;
}
}
// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure. Disappointing. A true
// region type system might be able to do better than this.
fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
self.iter {|a|
if prd(a) { blk(a) }
}
}
fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
self.iter {|a|
let b = cnv(a);
blk(b);
}
}
fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
self.iter {|a|
cnv(a).iter(blk)
}
}
fn foldl<A,B:copy,IA:iterable<A>>(self: IA, b0: B, blk: fn(B, A) -> B) -> B {
let b = b0;
self.iter {|a|
b = blk(b, a);
}
ret b;
}
fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}
fn repeat(times: uint, blk: fn()) {
let i = 0u;
while i < times {
blk();
i += 1u;
}
}
#[test]
fn test_enumerate() {
enumerate(["0", "1", "2"]) {|i,j|
assert #fmt["%u",i] == j;
}
}
#[test]
fn test_map_and_to_list() {
let a = bind vec::iter([0, 1, 2], _);
let b = bind map(a, {|i| i*2}, _);
let c = to_list(b);
assert c == [0, 2, 4];
}
#[test]
fn test_map_directly_on_vec() {
let b = bind map([0, 1, 2], {|i| i*2}, _);
let c = to_list(b);
assert c == [0, 2, 4];
}
#[test]
fn test_filter_on_int_range() {
fn is_even(&&i: int) -> bool {
ret (i % 2) == 0;
}
let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
assert l == [0, 2, 4, 6, 8];
}
#[test]
fn test_filter_on_uint_range() {
fn is_even(&&i: uint) -> bool {
ret (i % 2u) == 0u;
}
let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
assert l == [0u, 2u, 4u, 6u, 8u];
}
#[test]
fn test_flat_map_with_option() {
fn if_even(&&i: int) -> option<int> {
if (i % 2) == 0 { some(i) }
else { none }
}
let a = bind vec::iter([0, 1, 2], _);
let b = bind flat_map(a, if_even, _);
let c = to_list(b);
assert c == [0, 2];
}
#[test]
fn test_flat_map_with_list() {
fn repeat(&&i: int) -> [int] {
let r = [];
int::range(0, i) {|_j| r += [i]; }
r
}
let a = bind vec::iter([0, 1, 2, 3], _);
let b = bind flat_map(a, repeat, _);
let c = to_list(b);
#debug["c = %?", c];
assert c == [1, 2, 2, 3, 3, 3];
}
#[test]
fn test_repeat() {
let c = [],
i = 0u;
repeat(5u) {||
c += [(i * i)];
i += 1u;
};
#debug["c = %?", c];
assert c == [0u, 1u, 4u, 9u, 16u];
}

View File

@ -11,10 +11,10 @@ import core::tuple;
export crate_attrs, mod_attrs, fn_attrs, arg_attrs,
const_attrs, enum_attrs, variant_attrs, res_attrs,
iface_attrs, method_attrs;
iface_attrs, method_attrs, impl_attrs;
export parse_crate, parse_mod, parse_fn, parse_const,
parse_enum, parse_variant, parse_res,
parse_iface, parse_method;
parse_iface, parse_method, parse_impl;
type crate_attrs = {
name: option<str>
@ -63,6 +63,11 @@ type iface_attrs = {
desc: option<str>
};
type impl_attrs = {
brief: option<str>,
desc: option<str>
};
type method_attrs = fn_attrs;
#[cfg(test)]
@ -499,3 +504,7 @@ fn parse_iface(attrs: [ast::attribute]) -> iface_attrs {
fn parse_method(attrs: [ast::attribute]) -> method_attrs {
parse_fn(attrs)
}
fn parse_impl(attrs: [ast::attribute]) -> impl_attrs {
parse_basic(attrs)
}

View File

@ -26,7 +26,8 @@ fn run(
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(srv)
});
fold.fold_crate(fold, doc)
@ -55,11 +56,7 @@ fn fold_crate(
#[test]
fn should_replace_top_module_name_with_crate_name() {
let source = "#[link(name = \"bond\")];";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_crate(fold, doc);
let doc = test::mk_doc("#[link(name = \"bond\")];");
assert doc.topmod.name == "bond";
}
@ -105,22 +102,14 @@ fn fold_mod(fold: fold::fold<astsrv::srv>, doc: doc::moddoc) -> doc::moddoc {
#[test]
fn fold_mod_should_extract_mod_attributes() {
let source = "#[doc = \"test\"] mod a { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_mod(fold, doc.topmod.mods()[0]);
assert doc.desc == some("test");
let doc = test::mk_doc("#[doc = \"test\"] mod a { }");
assert doc.topmod.mods()[0].desc == some("test");
}
#[test]
fn fold_mod_should_extract_top_mod_attributes() {
let source = "#[doc = \"test\"];";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_mod(fold, doc.topmod);
assert doc.desc == some("test");
let doc = test::mk_doc("#[doc = \"test\"];");
assert doc.topmod.desc == some("test");
}
fn fold_fn(
@ -181,22 +170,14 @@ fn merge_ret_attrs(
#[test]
fn fold_fn_should_extract_fn_attributes() {
let source = "#[doc = \"test\"] fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_fn(fold, doc.topmod.fns()[0]);
assert doc.desc == some("test");
let doc = test::mk_doc("#[doc = \"test\"] fn a() -> int { }");
assert doc.topmod.fns()[0].desc == some("test");
}
#[test]
fn fold_fn_should_extract_arg_attributes() {
let source = "#[doc(args(a = \"b\"))] fn c(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_fn(fold, doc.topmod.fns()[0]);
assert doc.args[0].desc == some("b");
let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn c(a: bool) { }");
assert doc.topmod.fns()[0].args[0].desc == some("b");
}
#[test]
@ -223,12 +204,8 @@ fn fold_fn_should_preserve_sig() {
#[test]
fn fold_fn_should_extract_failure_conditions() {
let source = "#[doc(failure = \"what\")] fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_fn(fold, doc.topmod.fns()[0]);
assert doc.failure == some("what");
let doc = test::mk_doc("#[doc(failure = \"what\")] fn a() { }");
assert doc.topmod.fns()[0].failure == some("what");
}
fn fold_const(
@ -247,14 +224,10 @@ fn fold_const(
#[test]
fn fold_const_should_extract_docs() {
let source = "#[doc(brief = \"foo\", desc = \"bar\")]\
const a: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_const(fold, doc.topmod.consts()[0]);
assert doc.brief == some("foo");
assert doc.desc == some("bar");
let doc = test::mk_doc("#[doc(brief = \"foo\", desc = \"bar\")]\
const a: bool = true;");
assert doc.topmod.consts()[0].brief == some("foo");
assert doc.topmod.consts()[0].desc == some("bar");
}
fn fold_enum(
@ -295,24 +268,16 @@ fn fold_enum(
#[test]
fn fold_enum_should_extract_docs() {
let source = "#[doc(brief = \"a\", desc = \"b\")]\
enum a { v }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_enum(fold, doc.topmod.enums()[0]);
assert doc.brief == some("a");
assert doc.desc == some("b");
let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
enum a { v }");
assert doc.topmod.enums()[0].brief == some("a");
assert doc.topmod.enums()[0].desc == some("b");
}
#[test]
fn fold_enum_should_extract_variant_docs() {
let source = "enum a { #[doc = \"c\"] v }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_enum(fold, doc.topmod.enums()[0]);
assert doc.variants[0].desc == some("c");
let doc = test::mk_doc("enum a { #[doc = \"c\"] v }");
assert doc.topmod.enums()[0].variants[0].desc == some("c");
}
fn fold_res(
@ -345,26 +310,18 @@ fn fold_res(
#[test]
fn fold_res_should_extract_docs() {
let source = "#[doc(brief = \"a\", desc = \"b\")]\
resource r(b: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_res(fold, doc.topmod.resources()[0]);
assert doc.brief == some("a");
assert doc.desc == some("b");
let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
resource r(b: bool) { }");
assert doc.topmod.resources()[0].brief == some("a");
assert doc.topmod.resources()[0].desc == some("b");
}
#[test]
fn fold_res_should_extract_arg_docs() {
let source = "#[doc(args(a = \"b\"))]\
resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let fold = fold::default_seq_fold(srv);
let doc = fold_res(fold, doc.topmod.resources()[0]);
assert doc.args[0].name == "a";
assert doc.args[0].desc == some("b");
let doc = test::mk_doc("#[doc(args(a = \"b\"))]\
resource r(a: bool) { }");
assert doc.topmod.resources()[0].args[0].name == "a";
assert doc.topmod.resources()[0].args[0].desc == some("b");
}
fn fold_iface(
@ -398,9 +355,14 @@ fn merge_method_attrs(
(method.ident, attr_parser::parse_method(method.attrs))
}
}
_ {
fail "Undocumented invariant in merge_method_attrs";
ast_map::node_item(@{
node: ast::item_impl(_, _, _, methods), _
}) {
vec::map(methods) {|method|
(method.ident, attr_parser::parse_method(method.attrs))
}
}
_ { fail "unexpected item" }
}
};
@ -421,30 +383,77 @@ fn merge_method_attrs(
#[test]
fn should_extract_iface_docs() {
let source = "#[doc = \"whatever\"] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc = \"whatever\"] iface i { fn a(); }");
assert doc.topmod.ifaces()[0].desc == some("whatever");
}
#[test]
fn should_extract_iface_method_docs() {
let source = "iface i {\
#[doc(\
brief = \"brief\",\
desc = \"desc\",\
args(a = \"a\"),\
return = \"return\",\
failure = \"failure\")]\
fn f(a: bool) -> bool;\
}";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc(
"iface i {\
#[doc(\
brief = \"brief\",\
desc = \"desc\",\
args(a = \"a\"),\
return = \"return\",\
failure = \"failure\")]\
fn f(a: bool) -> bool;\
}");
assert doc.topmod.ifaces()[0].methods[0].brief == some("brief");
assert doc.topmod.ifaces()[0].methods[0].desc == some("desc");
assert doc.topmod.ifaces()[0].methods[0].args[0].desc == some("a");
assert doc.topmod.ifaces()[0].methods[0].return.desc == some("return");
assert doc.topmod.ifaces()[0].methods[0].failure == some("failure");
}
fn fold_impl(
fold: fold::fold<astsrv::srv>,
doc: doc::impldoc
) -> doc::impldoc {
let srv = fold.ctxt;
let doc = fold::default_seq_fold_impl(fold, doc);
let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_impl);
{
brief: attrs.brief,
desc: attrs.desc,
methods: merge_method_attrs(srv, doc.id, doc.methods)
with doc
}
}
#[test]
fn should_extract_impl_docs() {
let doc = test::mk_doc(
"#[doc = \"whatever\"] impl i for int { fn a() { } }");
assert doc.topmod.impls()[0].desc == some("whatever");
}
#[test]
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\")]\
fn f(a: bool) -> bool { }\
}");
assert doc.topmod.impls()[0].methods[0].brief == some("brief");
assert doc.topmod.impls()[0].methods[0].desc == some("desc");
assert doc.topmod.impls()[0].methods[0].args[0].desc == some("a");
assert doc.topmod.impls()[0].methods[0].return.desc == some("return");
assert doc.topmod.impls()[0].methods[0].failure == some("failure");
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
run(srv, doc)
}
}

View File

@ -167,4 +167,15 @@ iface the_shunned_house {
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) {
}
fn construct() -> bool {
fail;
}
}

View File

@ -21,7 +21,8 @@ fn run(
fold_fn: fold_fn,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(op)
});
fold.fold_crate(fold, doc)
@ -104,154 +105,181 @@ fn fold_iface(fold: fold::fold<op>, doc: doc::ifacedoc) -> doc::ifacedoc {
{
brief: maybe_apply_op(fold.ctxt, doc.brief),
desc: maybe_apply_op(fold.ctxt, doc.desc),
methods: vec::map(doc.methods) {|doc|
{
brief: maybe_apply_op(fold.ctxt, doc.brief),
desc: maybe_apply_op(fold.ctxt, doc.desc),
args: vec::map(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
}
methods: apply_to_methods(fold.ctxt, doc.methods)
with doc
}
}
fn apply_to_methods(op: op, docs: [doc::methoddoc]) -> [doc::methoddoc] {
vec::map(docs) {|doc|
{
brief: maybe_apply_op(op, doc.brief),
desc: maybe_apply_op(op, doc.desc),
args: vec::map(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)
with doc
}
}
}
fn fold_impl(fold: fold::fold<op>, doc: doc::impldoc) -> doc::impldoc {
{
brief: maybe_apply_op(fold.ctxt, doc.brief),
desc: maybe_apply_op(fold.ctxt, doc.desc),
methods: apply_to_methods(fold.ctxt, doc.methods)
with doc
}
}
#[test]
fn should_execute_op_on_enum_brief() {
let source = "#[doc(brief = \" a \")] enum a { b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("#[doc(brief = \" a \")] enum a { b }");
assert doc.topmod.enums()[0].brief == some("a");
}
#[test]
fn should_execute_op_on_enum_desc() {
let source = "#[doc(desc = \" a \")] enum a { b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("#[doc(desc = \" a \")] enum a { b }");
assert doc.topmod.enums()[0].desc == some("a");
}
#[test]
fn should_execute_op_on_variant_desc() {
let source = "enum a { #[doc = \" a \"] b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("enum a { #[doc = \" a \"] b }");
assert doc.topmod.enums()[0].variants[0].desc == some("a");
}
#[test]
fn should_execute_op_on_resource_brief() {
let source = "#[doc(brief = \" a \")] resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("#[doc(brief = \" a \")] resource r(a: bool) { }");
assert doc.topmod.resources()[0].brief == some("a");
}
#[test]
fn should_execute_op_on_resource_desc() {
let source = "#[doc(desc = \" a \")] resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("#[doc(desc = \" a \")] resource r(a: bool) { }");
assert doc.topmod.resources()[0].desc == some("a");
}
#[test]
fn should_execute_op_on_resource_args() {
let source = "#[doc(args(a = \" a \"))] resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"#[doc(args(a = \" a \"))] resource r(a: bool) { }");
assert doc.topmod.resources()[0].args[0].desc == some("a");
}
#[test]
fn should_execute_op_on_iface_brief() {
let source = "#[doc(brief = \" a \")] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"#[doc(brief = \" a \")] iface i { fn a(); }");
assert doc.topmod.ifaces()[0].brief == some("a");
}
#[test]
fn should_execute_op_on_iface_desc() {
let source = "#[doc(desc = \" a \")] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"#[doc(desc = \" a \")] iface i { fn a(); }");
assert doc.topmod.ifaces()[0].desc == some("a");
}
#[test]
fn should_execute_op_on_iface_method_brief() {
let source = "iface i { #[doc(brief = \" a \")] fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"iface i { #[doc(brief = \" a \")] fn a(); }");
assert doc.topmod.ifaces()[0].methods[0].brief == some("a");
}
#[test]
fn should_execute_op_on_iface_method_desc() {
let source = "iface i { #[doc(desc = \" a \")] fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"iface i { #[doc(desc = \" a \")] fn a(); }");
assert doc.topmod.ifaces()[0].methods[0].desc == some("a");
}
#[test]
fn should_execute_op_on_iface_method_args() {
let source = "iface i { #[doc(args(a = \" a \"))] fn a(a: bool); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"iface i { #[doc(args(a = \" a \"))] fn a(a: bool); }");
assert doc.topmod.ifaces()[0].methods[0].args[0].desc == some("a");
}
#[test]
fn should_execute_op_on_iface_method_return() {
let source = "iface i { #[doc(return = \" a \")] fn a() -> int; }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc(
"iface i { #[doc(return = \" a \")] fn a() -> int; }");
assert doc.topmod.ifaces()[0].methods[0].return.desc == some("a");
}
#[test]
fn should_execute_op_on_iface_method_failure_condition() {
let source = "iface i { #[doc(failure = \" a \")] fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass(str::trim)(srv, doc);
let doc = test::mk_doc("iface i { #[doc(failure = \" a \")] fn a(); }");
assert doc.topmod.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() { } }");
assert doc.topmod.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() { } }");
assert doc.topmod.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() { } }");
assert doc.topmod.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() { } }");
assert doc.topmod.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.topmod.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.topmod.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.topmod.impls()[0].methods[0].failure == some("a");
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
mk_pass(str::trim)(srv, doc)
}
}

View File

@ -23,7 +23,8 @@ fn run(
fold_fn: fold_fn,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(())
});
fold.fold_crate(fold, doc)
@ -104,83 +105,102 @@ fn fold_iface(fold: fold::fold<()>, doc: doc::ifacedoc) -> doc::ifacedoc {
}
}
fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
let doc =fold::default_seq_fold_impl(fold, doc);
let (brief, desc) = modify(doc.brief, doc.desc);
{
brief: brief,
desc: desc,
methods: vec::map(doc.methods) {|doc|
let (brief, desc) = modify(doc.brief, doc.desc);
{
brief: brief,
desc: desc
with doc
}
}
with doc
}
}
#[test]
fn should_promote_mod_desc() {
let source = "#[doc(desc = \"desc\")] mod m { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(desc = \"desc\")] mod m { }");
assert doc.topmod.mods()[0].brief == some("desc");
assert doc.topmod.mods()[0].desc == none;
}
#[test]
fn should_promote_const_desc() {
let source = "#[doc(desc = \"desc\")] const a: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(desc = \"desc\")] const a: bool = true;");
assert doc.topmod.consts()[0].brief == some("desc");
assert doc.topmod.consts()[0].desc == none;
}
#[test]
fn should_promote_fn_desc() {
let source = "#[doc(desc = \"desc\")] fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(desc = \"desc\")] fn a() { }");
assert doc.topmod.fns()[0].brief == some("desc");
assert doc.topmod.fns()[0].desc == none;
}
#[test]
fn should_promote_enum_desc() {
let source = "#[doc(desc = \"desc\")] enum a { b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(desc = \"desc\")] enum a { b }");
assert doc.topmod.enums()[0].brief == some("desc");
assert doc.topmod.enums()[0].desc == none;
}
#[test]
fn should_promote_resource_desc() {
let source = "#[doc(desc = \"desc\")] resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc(
"#[doc(desc = \"desc\")] resource r(a: bool) { }");
assert doc.topmod.resources()[0].brief == some("desc");
assert doc.topmod.resources()[0].desc == none;
}
#[test]
fn should_promote_iface_desc() {
let source = "#[doc(desc = \"desc\")] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(desc = \"desc\")] iface i { fn a(); }");
assert doc.topmod.ifaces()[0].brief == some("desc");
assert doc.topmod.ifaces()[0].desc == none;
}
#[test]
fn should_promote_iface_method_desc() {
let source = "iface i { #[doc(desc = \"desc\")] fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { #[doc(desc = \"desc\")] fn a(); }");
assert doc.topmod.ifaces()[0].methods[0].brief == some("desc");
assert doc.topmod.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.topmod.impls()[0].brief == some("desc");
assert doc.topmod.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() { } }");
assert doc.topmod.impls()[0].methods[0].brief == some("desc");
assert doc.topmod.impls()[0].methods[0].desc == none;
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
run(srv, doc)
}
}
fn modify(
brief: option<str>,
desc: option<str>

View File

@ -12,7 +12,8 @@ enum itemtag {
fntag(fndoc),
enumtag(enumdoc),
restag(resdoc),
ifacetag(ifacedoc)
ifacetag(ifacedoc),
impltag(impldoc)
}
type moddoc = {
@ -96,6 +97,16 @@ type methoddoc = {
sig: option<str>
};
type impldoc = {
id: ast_id,
name: str,
brief: option<str>,
desc: option<str>,
iface_ty: option<str>,
self_ty: option<str>,
methods: [methoddoc]
};
#[doc = "Some helper methods on moddoc, mostly for testing"]
impl util for moddoc {
@ -152,6 +163,15 @@ impl util for moddoc {
}
}
}
fn impls() -> [impldoc] {
vec::filter_map(*self.items) {|itemtag|
alt itemtag {
impltag(impldoc) { some(impldoc) }
_ { none }
}
}
}
}
#[doc = "Helper methods on itemtag"]
@ -164,6 +184,7 @@ impl util for itemtag {
doc::enumtag({name, _}) { name }
doc::restag({name, _}) { name }
doc::ifacetag({name, _}) { name }
doc::impltag({name, _}) { name }
}
}
}

View File

@ -75,6 +75,11 @@ fn moddoc_from_mod(
ifacedoc_from_iface(methods, item.ident, item.id)
))
}
ast::item_impl(_, _, _, methods) {
some(doc::impltag(
impldoc_from_impl(methods, item.ident, item.id)
))
}
_ {
none
}
@ -140,9 +145,7 @@ fn constdoc_from_const(
#[test]
fn should_extract_const_name_and_id() {
let source = "const a: int = 0;";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("const a: int = 0;");
assert doc.topmod.consts()[0].id != 0;
assert doc.topmod.consts()[0].name == "a";
}
@ -177,18 +180,14 @@ fn variantdoc_from_variant(variant: ast::variant) -> doc::variantdoc {
#[test]
fn should_extract_enums() {
let source = "enum e { v }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("enum e { v }");
assert doc.topmod.enums()[0].id != 0;
assert doc.topmod.enums()[0].name == "e";
}
#[test]
fn should_extract_enum_variants() {
let source = "enum e { v }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("enum e { v }");
assert doc.topmod.enums()[0].variants[0].name == "v";
}
@ -209,18 +208,14 @@ fn resdoc_from_resource(
#[test]
fn should_extract_resources() {
let source = "resource r(b: bool) { }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("resource r(b: bool) { }");
assert doc.topmod.resources()[0].id != 0;
assert doc.topmod.resources()[0].name == "r";
}
#[test]
fn should_extract_resource_args() {
let source = "resource r(b: bool) { }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("resource r(b: bool) { }");
assert doc.topmod.resources()[0].args[0].name == "b";
}
@ -253,45 +248,93 @@ fn ifacedoc_from_iface(
#[test]
fn should_extract_ifaces() {
let source = "iface i { fn f(); }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("iface i { fn f(); }");
assert doc.topmod.ifaces()[0].name == "i";
}
#[test]
fn should_extract_iface_methods() {
let source = "iface i { fn f(); }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("iface i { fn f(); }");
assert doc.topmod.ifaces()[0].methods[0].name == "f";
}
#[test]
fn should_extract_iface_method_args() {
let source = "iface i { fn f(a: bool); }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = test::mk_doc("iface i { fn f(a: bool); }");
assert doc.topmod.ifaces()[0].methods[0].args[0].name == "a";
}
fn impldoc_from_impl(
methods: [@ast::method],
name: str,
id: ast::node_id
) -> doc::impldoc {
{
id: id,
name: name,
brief: none,
desc: none,
iface_ty: none,
self_ty: none,
methods: vec::map(methods) {|method|
{
name: method.ident,
brief: none,
desc: none,
args: argdocs_from_args(method.decl.inputs),
return: {
desc: none,
ty: none
},
failure: none,
sig: none
}
}
}
}
#[test]
fn should_extract_impls_with_names() {
let doc = test::mk_doc("impl i for int { fn a() { } }");
assert doc.topmod.impls()[0].name == "i";
}
#[test]
fn should_extract_impls_without_names() {
let doc = test::mk_doc("impl of i for int { fn a() { } }");
assert doc.topmod.impls()[0].name == "i";
}
#[test]
fn should_extract_impl_methods() {
let doc = test::mk_doc("impl i for int { fn f() { } }");
assert doc.topmod.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.topmod.impls()[0].methods[0].args[0].name == "a";
}
#[cfg(test)]
mod tests {
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let ast = parse::from_str(source);
extract(ast, "")
}
#[test]
fn extract_empty_crate() {
let source = ""; // empty crate
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = mk_doc("");
assert vec::is_empty(doc.topmod.mods());
assert vec::is_empty(doc.topmod.fns());
}
#[test]
fn extract_mods() {
let source = "mod a { mod b { } mod c { } }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = mk_doc("mod a { mod b { } mod c { } }");
assert doc.topmod.mods()[0].name == "a";
assert doc.topmod.mods()[0].mods()[0].name == "b";
assert doc.topmod.mods()[0].mods()[1].name == "c";
@ -299,36 +342,28 @@ mod tests {
#[test]
fn extract_mods_deep() {
let source = "mod a { mod b { mod c { } } }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = mk_doc("mod a { mod b { mod c { } } }");
assert doc.topmod.mods()[0].mods()[0].mods()[0].name == "c";
}
#[test]
fn extract_should_set_mod_ast_id() {
let source = "mod a { }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = mk_doc("mod a { }");
assert doc.topmod.mods()[0].id != 0;
}
#[test]
fn extract_fns() {
let source =
let doc = mk_doc(
"fn a() { } \
mod b { fn c() { } }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
mod b { fn c() { } }");
assert doc.topmod.fns()[0].name == "a";
assert doc.topmod.mods()[0].fns()[0].name == "c";
}
#[test]
fn extract_should_set_fn_ast_id() {
let source = "fn a() { }";
let ast = parse::from_str(source);
let doc = extract(ast, "");
let doc = mk_doc("fn a() { }");
assert doc.topmod.fns()[0].id != 0;
}

View File

@ -11,6 +11,7 @@ export default_seq_fold_const;
export default_seq_fold_enum;
export default_seq_fold_res;
export default_seq_fold_iface;
export default_seq_fold_impl;
enum fold<T> = t<T>;
@ -21,6 +22,7 @@ type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
type t<T> = {
ctxt: T,
@ -30,7 +32,8 @@ type t<T> = {
fold_const: fold_const<T>,
fold_enum: fold_enum<T>,
fold_res: fold_res<T>,
fold_iface: fold_iface<T>
fold_iface: fold_iface<T>,
fold_impl: fold_impl<T>
};
@ -44,7 +47,8 @@ fn mk_fold<T:copy>(
fold_const: fold_const<T>,
fold_enum: fold_enum<T>,
fold_res: fold_res<T>,
fold_iface: fold_iface<T>
fold_iface: fold_iface<T>,
fold_impl: fold_impl<T>
) -> fold<T> {
fold({
ctxt: ctxt,
@ -54,7 +58,8 @@ fn mk_fold<T:copy>(
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
})
}
@ -67,7 +72,8 @@ fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
{|f, d| default_seq_fold_const(f, d)},
{|f, d| default_seq_fold_enum(f, d)},
{|f, d| default_seq_fold_res(f, d)},
{|f, d| default_seq_fold_iface(f, d)}
{|f, d| default_seq_fold_iface(f, d)},
{|f, d| default_seq_fold_impl(f, d)}
)
}
@ -105,6 +111,9 @@ fn default_seq_fold_mod<T>(
doc::ifacetag(ifacedoc) {
doc::ifacetag(fold.fold_iface(fold, ifacedoc))
}
doc::impltag(impldoc) {
doc::impltag(fold.fold_impl(fold, impldoc))
}
}
}
with doc
@ -146,6 +155,13 @@ fn default_seq_fold_iface<T>(
doc
}
fn default_seq_fold_impl<T>(
_fold: fold<T>,
doc: doc::impldoc
) -> doc::impldoc {
doc
}
#[test]
fn default_fold_should_produce_same_doc() {
let source = "mod a { fn b() { } mod c { fn d() { } } }";

View File

@ -138,6 +138,7 @@ fn write_mod_contents(
doc::enumtag(enumdoc) { write_enum(ctxt, enumdoc) }
doc::restag(resdoc) { write_res(ctxt, resdoc) }
doc::ifacetag(ifacedoc) { write_iface(ctxt, ifacedoc) }
doc::impltag(impldoc) { write_impl(ctxt, impldoc) }
}
}
}
@ -647,6 +648,101 @@ fn should_write_iface_method_failure_conditions() {
assert str::contains(markdown, "Failure conditions: nuked");
}
fn write_impl(ctxt: ctxt, doc: doc::impldoc) {
assert option::is_some(doc.self_ty);
let self_ty = option::get(doc.self_ty);
alt doc.iface_ty {
some(iface_ty) {
write_header(ctxt, h2,
#fmt("Implementation `%s` of `%s` for `%s`",
doc.name, iface_ty, self_ty));
}
none {
write_header(ctxt, h2,
#fmt("Implementation `%s` for `%s`",
doc.name, self_ty));
}
}
write_brief(ctxt, doc.brief);
write_desc(ctxt, doc.desc);
write_methods(ctxt, doc.methods);
}
#[test]
fn should_write_impl_header() {
let markdown = test::render("impl i for int { fn a() { } }");
assert str::contains(markdown, "## Implementation `i` for `int`");
}
#[test]
fn should_write_impl_header_with_iface() {
let markdown = test::render("impl i of j for int { fn a() { } }");
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() { } }");
assert str::contains(markdown, "desc");
}
#[test]
fn should_write_impl_method_header() {
let markdown = test::render(
"impl i for int { fn a() { } }");
assert str::contains(markdown, "### Method `a`");
}
#[test]
fn should_write_impl_method_signature() {
let markdown = test::render(
"impl i for int { fn a() { } }");
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\nArguments:\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`: `int`\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 { fn a() -> int { } }");
assert str::contains(markdown, "Returns `int`");
}
#[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");
}
#[cfg(test)]
mod test {
fn render(source: str) -> str {

View File

@ -23,7 +23,8 @@ fn run(
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(ctxt)
});
fold.fold_crate(fold, doc)
@ -84,6 +85,14 @@ fn fold_mod(
none
}
}
doc::impltag(impldoc) {
let doc = fold.fold_impl(fold, impldoc);
if fold.ctxt.have_docs {
some(doc::impltag(doc))
} else {
none
}
}
_ { some(itemtag) }
}
}
@ -138,21 +147,13 @@ fn prune_return(doc: doc::retdoc) -> doc::retdoc {
#[test]
fn should_elide_undocumented_arguments() {
let source = "#[doc = \"hey\"] fn a(b: int) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
assert vec::is_empty(doc.topmod.fns()[0].args);
}
#[test]
fn should_not_elide_fns_with_documented_arguments() {
let source = "#[doc(args(a = \"b\"))] fn a(a: int) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(args(a = \"b\"))] fn a(a: int) { }");
assert vec::is_not_empty(doc.topmod.fns());
}
@ -169,49 +170,31 @@ fn should_elide_undocumented_return_values() {
#[test]
fn should_not_elide_fns_with_documented_failure_conditions() {
let source = "#[doc(failure = \"yup\")] fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(failure = \"yup\")] fn a() { }");
assert vec::is_not_empty(doc.topmod.fns());
}
#[test]
fn should_elide_undocumented_mods() {
let source = "mod a { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { }");
assert vec::is_empty(doc.topmod.mods());
}
#[test]
fn should_not_elide_undocument_mods_with_documented_mods() {
let source = "mod a { #[doc = \"b\"] mod b { } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { #[doc = \"b\"] mod b { } }");
assert vec::is_not_empty(doc.topmod.mods());
}
#[test]
fn should_not_elide_undocument_mods_with_documented_fns() {
let source = "mod a { #[doc = \"b\"] fn b() { } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { #[doc = \"b\"] fn b() { } }");
assert vec::is_not_empty(doc.topmod.mods());
}
#[test]
fn should_elide_undocumented_fns() {
let source = "fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("fn a() { }");
assert vec::is_empty(doc.topmod.fns());
}
@ -228,10 +211,7 @@ fn fold_const(
#[test]
fn should_elide_undocumented_consts() {
let source = "const a: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("const a: bool = true;");
assert vec::is_empty(doc.topmod.consts());
}
@ -255,31 +235,19 @@ fn fold_enum(fold: fold::fold<ctxt>, doc: doc::enumdoc) -> doc::enumdoc {
#[test]
fn should_elide_undocumented_enums() {
let source = "enum a { b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("enum a { b }");
assert vec::is_empty(doc.topmod.enums());
}
#[test]
fn should_elide_undocumented_variants() {
let source = "#[doc = \"a\"] enum a { b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc = \"a\"] enum a { b }");
assert vec::is_empty(doc.topmod.enums()[0].variants);
}
#[test]
fn should_not_elide_enums_with_documented_variants() {
let source = "enum a { #[doc = \"a\"] b }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("enum a { #[doc = \"a\"] b }");
assert vec::is_not_empty(doc.topmod.enums());
}
@ -303,32 +271,21 @@ fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
#[test]
fn should_elide_undocumented_resources() {
let source = "resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("resource r(a: bool) { }");
assert vec::is_empty(doc.topmod.resources());
}
#[test]
fn should_elide_undocumented_resource_args() {
let source = "#[doc = \"drunk\"]\
resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc = \"drunk\"]\
resource r(a: bool) { }");
assert vec::is_empty(doc.topmod.resources()[0].args);
}
#[test]
fn should_not_elide_resources_with_documented_args() {
let source = "#[doc(args(a = \"drunk\"))]\
resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc(args(a = \"drunk\"))]\
resource r(a: bool) { }");
assert vec::is_not_empty(doc.topmod.resources());
}
@ -338,86 +295,133 @@ fn fold_iface(
) -> doc::ifacedoc {
let doc = fold::default_seq_fold_iface(fold, doc);
let doc = {
methods: vec::map(doc.methods) {|doc|
{
args: prune_args(doc.args),
return: prune_return(doc.return)
with doc
}
}
methods: prune_methods(doc.methods)
with doc
};
let methods_have_docs = vec::foldl(false, doc.methods) {|accum, doc|
fold.ctxt.have_docs =
doc.brief != none
|| doc.desc != none
|| methods_have_docs(doc.methods);
ret doc;
}
fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
vec::map(docs) {|doc|
{
args: prune_args(doc.args),
return: prune_return(doc.return)
with doc
}
}
}
fn methods_have_docs(docs: [doc::methoddoc]) -> bool {
vec::foldl(false, docs) {|accum, doc|
accum
|| doc.brief != none
|| doc.desc != none
|| vec::is_not_empty(doc.args)
|| doc.return.desc != none
|| doc.failure != none
};
fold.ctxt.have_docs =
doc.brief != none
|| doc.desc != none
|| methods_have_docs;
ret doc;
}
}
#[test]
fn should_elide_undocumented_ifaces() {
let source = "iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { fn a(); }");
assert vec::is_empty(doc.topmod.ifaces());
}
#[test]
fn should_not_elide_documented_ifaces() {
let source = "#[doc = \"hey\"] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
assert vec::is_not_empty(doc.topmod.ifaces());
}
#[test]
fn should_not_elide_ifaces_with_documented_methods() {
let source = "iface i { #[doc = \"hey\"] fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { #[doc = \"hey\"] fn a(); }");
assert vec::is_not_empty(doc.topmod.ifaces());
}
#[test]
fn should_not_elide_undocumented_methods() {
let source = "#[doc = \"hey\"] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
fn should_not_elide_undocumented_iface_methods() {
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
assert vec::is_not_empty(doc.topmod.ifaces()[0].methods);
}
#[test]
fn should_elide_undocumented_method_args() {
let source = "#[doc = \"hey\"] iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
fn should_elide_undocumented_iface_method_args() {
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
assert vec::is_empty(doc.topmod.ifaces()[0].methods[0].args);
}
#[test]
fn should_elide_undocumented_method_return_values() {
let source = "#[doc = \"hey\"] iface i { fn a() -> int; }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
fn should_elide_undocumented_iface_method_return_values() {
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a() -> int; }");
assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
}
}
fn fold_impl(
fold: fold::fold<ctxt>,
doc: doc::impldoc
) -> doc::impldoc {
let doc = fold::default_seq_fold_impl(fold, doc);
let doc = {
methods: prune_methods(doc.methods)
with 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.topmod.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.topmod.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.topmod.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.topmod.impls()[0].methods);
}
#[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.topmod.impls()[0].methods[0].args);
}
#[test]
fn should_elide_undocumented_impl_method_return_values() {
let doc = test::mk_doc(
"#[doc = \"hey\"] impl i for int { fn a() -> int { } }");
assert doc.topmod.impls()[0].methods[0].return.ty == none;
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
run(srv, doc)
}
}

View File

@ -132,119 +132,99 @@ fn is_exported_from_crate(
#[test]
fn should_prune_unexported_fns() {
let source = "mod b { export a; fn a() { } fn b() { } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("mod b { export a; fn a() { } fn b() { } }");
assert vec::len(doc.topmod.mods()[0].fns()) == 1u;
}
#[test]
fn should_prune_unexported_fns_from_top_mod() {
let source = "export a; fn a() { } fn b() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export a; fn a() { } fn b() { }");
assert vec::len(doc.topmod.fns()) == 1u;
}
#[test]
fn should_prune_unexported_modules() {
let source = "mod a { export a; mod a { } mod b { } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { export a; mod a { } mod b { } }");
assert vec::len(doc.topmod.mods()[0].mods()) == 1u;
}
#[test]
fn should_prune_unexported_modules_from_top_mod() {
let source = "export a; mod a { } mod b { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export a; mod a { } mod b { }");
assert vec::len(doc.topmod.mods()) == 1u;
}
#[test]
fn should_prune_unexported_consts() {
let source = "mod a { export a; \
const a: bool = true; \
const b: bool = true; }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc(
"mod a { export a; \
const a: bool = true; \
const b: bool = true; }");
assert vec::len(doc.topmod.mods()[0].consts()) == 1u;
}
#[test]
fn should_prune_unexported_consts_from_top_mod() {
let source = "export a; const a: bool = true; const b: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc(
"export a; const a: bool = true; const b: bool = true;");
assert vec::len(doc.topmod.consts()) == 1u;
}
#[test]
fn should_prune_unexported_enums_from_top_mod() {
let source = "export a; mod a { } enum b { c }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export a; mod a { } enum b { c }");
assert vec::len(doc.topmod.enums()) == 0u;
}
#[test]
fn should_prune_unexported_enums() {
let source = "mod a { export a; mod a { } enum b { c } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { export a; mod a { } enum b { c } }");
assert vec::len(doc.topmod.mods()[0].enums()) == 0u;
}
#[test]
fn should_prune_unexported_variants_from_top_mod() {
let source = "export b::{}; enum b { c }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export b::{}; enum b { c }");
assert vec::len(doc.topmod.enums()[0].variants) == 0u;
}
#[test]
fn should_prune_unexported_variants() {
let source = "mod a { export b::{}; enum b { c } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("mod a { export b::{}; enum b { c } }");
assert vec::len(doc.topmod.mods()[0].enums()[0].variants) == 0u;
}
#[test]
fn should_prune_unexported_resources_from_top_mod() {
let source = "export a; mod a { } resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export a; mod a { } resource r(a: bool) { }");
assert vec::is_empty(doc.topmod.resources());
}
#[test]
fn should_prune_unexported_resources() {
let source = "mod a { export a; mod a { } resource r(a: bool) { } }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc(
"mod a { export a; mod a { } resource r(a: bool) { } }");
assert vec::is_empty(doc.topmod.mods()[0].resources());
}
#[test]
fn should_prune_unexported_ifaces_from_top_mod() {
let source = "export a; mod a { } iface b { fn c(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("export a; mod a { } iface b { fn c(); }");
assert vec::is_empty(doc.topmod.ifaces());
}
#[test]
fn should_prune_unexported_impls_from_top_mod() {
let doc = test::mk_doc(
"export a; mod a { } impl b for int { fn c() { } }");
assert vec::is_empty(doc.topmod.impls())
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
run(srv, doc)
}
}

View File

@ -15,69 +15,55 @@ fn mk_pass() -> pass {
#[test]
fn should_trim_mod() {
let source = "#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
mod m { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
mod m { }");
assert doc.topmod.mods()[0].brief == some("brief");
assert doc.topmod.mods()[0].desc == some("desc");
}
#[test]
fn should_trim_const() {
let source = "#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
const a: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
const a: bool = true;");
assert doc.topmod.consts()[0].brief == some("brief");
assert doc.topmod.consts()[0].desc == some("desc");
}
#[test]
fn should_trim_fn() {
let source = "#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
desc = \"\ndesc\n\")] \
fn a() { }");
assert doc.topmod.fns()[0].brief == some("brief");
assert doc.topmod.fns()[0].desc == some("desc");
}
#[test]
fn should_trim_args() {
let source = "#[doc(args(a = \"\na\n\"))] fn a(a: int) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(args(a = \"\na\n\"))] fn a(a: int) { }");
assert doc.topmod.fns()[0].args[0].desc == some("a");
}
#[test]
fn should_trim_ret() {
let source = "#[doc(return = \"\na\n\")] fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(return = \"\na\n\")] fn a() -> int { }");
assert doc.topmod.fns()[0].return.desc == some("a");
}
#[test]
fn should_trim_failure_conditions() {
let source = "#[doc(failure = \"\na\n\")] fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
let doc = mk_pass()(srv, doc);
let doc = test::mk_doc("#[doc(failure = \"\na\n\")] fn a() -> int { }");
assert doc.topmod.fns()[0].failure == some("a");
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = attr_pass::mk_pass()(srv, doc);
mk_pass()(srv, doc)
}
}

View File

@ -20,7 +20,8 @@ fn run(
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
fold_iface: fold_iface
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(srv)
});
fold.fold_crate(fold, doc)
@ -59,10 +60,7 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
#[test]
fn should_add_fn_sig() {
let source = "fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("fn a() -> int { }");
assert doc.topmod.fns()[0].sig == some("fn a() -> int");
}
@ -106,19 +104,13 @@ fn ret_ty_to_str(decl: ast::fn_decl) -> option<str> {
#[test]
fn should_add_fn_ret_types() {
let source = "fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("fn a() -> int { }");
assert doc.topmod.fns()[0].return.ty == some("int");
}
#[test]
fn should_not_add_nil_ret_type() {
let source = "fn a() { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("fn a() { }");
assert doc.topmod.fns()[0].return.ty == none;
}
@ -164,10 +156,7 @@ fn decl_arg_tys(decl: ast::fn_decl) -> [(str, str)] {
#[test]
fn should_add_arg_types() {
let source = "fn a(b: int, c: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("fn a(b: int, c: bool) { }");
let fn_ = doc.topmod.fns()[0];
assert fn_.args[0].ty == some("int");
assert fn_.args[1].ty == some("bool");
@ -198,10 +187,7 @@ fn fold_const(
#[test]
fn should_add_const_types() {
let source = "const a: bool = true;";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("const a: bool = true;");
assert doc.topmod.consts()[0].ty == some("bool");
}
@ -240,10 +226,7 @@ fn fold_enum(
#[test]
fn should_add_variant_sigs() {
let source = "enum a { b(int) }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("enum a { b(int) }");
assert doc.topmod.enums()[0].variants[0].sig == some("b(int)");
}
@ -271,19 +254,13 @@ fn fold_res(
#[test]
fn should_add_resource_sigs() {
let source = "resource r(b: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("resource r(b: bool) { }");
assert doc.topmod.resources()[0].sig == some("resource r(b: bool)");
}
#[test]
fn should_add_resource_arg_tys() {
let source = "resource r(a: bool) { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("resource r(a: bool) { }");
assert doc.topmod.resources()[0].args[0].ty == some("bool");
}
@ -291,30 +268,35 @@ fn fold_iface(
fold: fold::fold<astsrv::srv>,
doc: doc::ifacedoc
) -> doc::ifacedoc {
let srv = fold.ctxt;
{
methods: vec::map(doc.methods) {|methoddoc|
{
args: merge_method_arg_tys(
srv,
doc.id,
methoddoc.args,
methoddoc.name),
return: merge_method_ret_ty(
srv,
doc.id,
methoddoc.return,
methoddoc.name),
sig: get_method_sig(srv, doc.id, methoddoc.name)
with methoddoc
}
}
methods: merge_methods(fold.ctxt, doc.id, doc.methods)
with doc
}
}
fn merge_methods(
srv: astsrv::srv,
item_id: doc::ast_id,
docs: [doc::methoddoc]
) -> [doc::methoddoc] {
vec::map(docs) {|doc|
{
args: merge_method_arg_tys(
srv,
item_id,
doc.args,
doc.name),
return: merge_method_ret_ty(
srv,
item_id,
doc.return,
doc.name),
sig: get_method_sig(srv, item_id, doc.name)
with doc
}
}
}
fn merge_method_ret_ty(
srv: astsrv::srv,
item_id: doc::ast_id,
@ -351,7 +333,19 @@ fn get_method_ret_ty(
_ { fail "get_method_ret_ty: undocumented invariant"; }
}
}
_ { fail "get_method_ret_ty: undocumented invariant"; }
ast_map::node_item(@{
node: ast::item_impl(_, _, _, methods), _
}) {
alt vec::find(methods) {|method|
method.ident == method_name
} {
some(method) {
ret_ty_to_str(method.decl)
}
_ { fail "get_method_ret_ty: undocumented invariant"; }
}
}
_ { fail }
}
}
}
@ -372,10 +366,22 @@ fn get_method_sig(
some(method) {
some(pprust::fun_to_str(method.decl, method.ident, []))
}
_ { fail "get_method_ret_sig: undocumented invariant"; }
_ { fail "get_method_sig: undocumented invariant"; }
}
}
_ { fail "get_method_ret_sig: undocumented invariant"; }
ast_map::node_item(@{
node: ast::item_impl(_, _, _, methods), _
}) {
alt vec::find(methods) {|method|
method.ident == method_name
} {
some(method) {
some(pprust::fun_to_str(method.decl, method.ident, []))
}
_ { fail "get_method_sig: undocumented invariant"; }
}
}
_ { fail "get_method_sig: undocumented invariant"; }
}
}
}
@ -412,48 +418,130 @@ fn get_method_arg_tys(
some(method) {
decl_arg_tys(method.decl)
}
_ { fail "get_method_arg_tys: undocumented invariant"; }
_ { fail "get_method_arg_tys: expected method"; }
}
}
_ { fail "get_method_arg_tys: undocumented invariant"; }
ast_map::node_item(@{
node: ast::item_impl(_, _, _, methods), _
}) {
alt vec::find(methods) {|method|
method.ident == method_name
} {
some(method) {
decl_arg_tys(method.decl)
}
_ { fail "get_method_arg_tys: expected method"; }
}
}
_ { fail }
}
}
}
#[test]
fn should_add_iface_method_sigs() {
let source = "iface i { fn a() -> int; }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { fn a() -> int; }");
assert doc.topmod.ifaces()[0].methods[0].sig == some("fn a() -> int");
}
#[test]
fn should_add_iface_method_ret_types() {
let source = "iface i { fn a() -> int; }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { fn a() -> int; }");
assert doc.topmod.ifaces()[0].methods[0].return.ty == some("int");
}
#[test]
fn should_not_add_iface_method_nil_ret_type() {
let source = "iface i { fn a(); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { fn a(); }");
assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
}
#[test]
fn should_add_iface_method_arg_types() {
let source = "iface i { fn a(b: int, c: bool); }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = run(srv, doc);
let doc = test::mk_doc("iface i { fn a(b: int, c: bool); }");
let fn_ = doc.topmod.ifaces()[0].methods[0];
assert fn_.args[0].ty == some("int");
assert fn_.args[1].ty == some("bool");
}
fn fold_impl(
fold: fold::fold<astsrv::srv>,
doc: doc::impldoc
) -> doc::impldoc {
let srv = fold.ctxt;
let (iface_ty, self_ty) = astsrv::exec(srv) {|ctxt|
alt ctxt.ast_map.get(doc.id) {
ast_map::node_item(@{
node: ast::item_impl(_, iface_ty, self_ty, _), _
}) {
let iface_ty = option::map(iface_ty) {|iface_ty|
pprust::ty_to_str(iface_ty)
};
(iface_ty, some(pprust::ty_to_str(self_ty)))
}
_ { fail "expected impl" }
}
};
{
iface_ty: iface_ty,
self_ty: self_ty,
methods: merge_methods(fold.ctxt, doc.id, doc.methods)
with doc
}
}
#[test]
fn should_add_impl_iface_ty() {
let doc = test::mk_doc("impl i of j for int { fn a() { } }");
assert doc.topmod.impls()[0].iface_ty == some("j");
}
#[test]
fn should_not_add_impl_iface_ty_if_none() {
let doc = test::mk_doc("impl i for int { fn a() { } }");
assert doc.topmod.impls()[0].iface_ty == none;
}
#[test]
fn should_add_impl_self_ty() {
let doc = test::mk_doc("impl i for int { fn a() { } }");
assert doc.topmod.impls()[0].self_ty == some("int");
}
#[test]
fn should_add_impl_method_sigs() {
let doc = test::mk_doc("impl i for int { fn a() -> int { fail } }");
assert doc.topmod.impls()[0].methods[0].sig == some("fn a() -> int");
}
#[test]
fn should_add_impl_method_ret_types() {
let doc = test::mk_doc("impl i for int { fn a() -> int { fail } }");
assert doc.topmod.impls()[0].methods[0].return.ty == some("int");
}
#[test]
fn should_not_add_impl_method_nil_ret_type() {
let doc = test::mk_doc("impl i for int { fn a() { } }");
assert doc.topmod.impls()[0].methods[0].return.ty == none;
}
#[test]
fn should_add_impl_method_arg_types() {
let doc = test::mk_doc("impl i for int { fn a(b: int, c: bool) { } }");
let fn_ = doc.topmod.impls()[0].methods[0];
assert fn_.args[0].ty == some("int");
assert fn_.args[1].ty == some("bool");
}
#[cfg(test)]
mod test {
fn mk_doc(source: str) -> doc::cratedoc {
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
run(srv, doc)
}
}