diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index b90c1c16d1a8..3bc5a0319493 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -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
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
new file mode 100644
index 000000000000..7aa08a6980c3
--- /dev/null
+++ b/src/libcore/iter.rs
@@ -0,0 +1,171 @@
+iface iterable {
+ fn iter(blk: fn(A));
+}
+
+impl of iterable 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 for fn@(fn(int)) {
+ fn iter(blk: fn(&&int)) {
+ self {|i| blk(i)}
+ }
+}
+
+impl of iterable for fn@(fn(uint)) {
+ fn iter(blk: fn(&&uint)) {
+ self {|i| blk(i)}
+ }
+}
+
+impl of iterable for [A] {
+ fn iter(blk: fn(A)) {
+ vec::iter(self, blk)
+ }
+}
+
+impl of iterable for option {
+ fn iter(blk: fn(A)) {
+ option::may(self, blk)
+ }
+}
+
+fn enumerate>(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>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
+ self.iter {|a|
+ if prd(a) { blk(a) }
+ }
+}
+
+fn map>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
+ self.iter {|a|
+ let b = cnv(a);
+ blk(b);
+ }
+}
+
+fn flat_map,IB:iterable>(
+ self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
+ self.iter {|a|
+ cnv(a).iter(blk)
+ }
+}
+
+fn foldl>(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>(self: IA) -> [A] {
+ foldl::(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 {
+ 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];
+}
+
+
diff --git a/src/rustdoc/attr_parser.rs b/src/rustdoc/attr_parser.rs
index 9d886b6d4c91..818efe018fe0 100644
--- a/src/rustdoc/attr_parser.rs
+++ b/src/rustdoc/attr_parser.rs
@@ -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
@@ -63,6 +63,11 @@ type iface_attrs = {
desc: option
};
+type impl_attrs = {
+ brief: option,
+ desc: option
+};
+
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)
+}
\ No newline at end of file
diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs
index 91e065f310b0..4e0c85c8ac38 100644
--- a/src/rustdoc/attr_pass.rs
+++ b/src/rustdoc/attr_pass.rs
@@ -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, 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,
+ 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)
+ }
+}
\ No newline at end of file
diff --git a/src/rustdoc/demo.rs b/src/rustdoc/demo.rs
index 924c7d73ee64..4feae4106a5f 100644
--- a/src/rustdoc/demo.rs
+++ b/src/rustdoc/demo.rs
@@ -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;
+ }
}
\ No newline at end of file
diff --git a/src/rustdoc/desc_pass.rs b/src/rustdoc/desc_pass.rs
index c2ebde8b1a04..317c1f70a437 100644
--- a/src/rustdoc/desc_pass.rs
+++ b/src/rustdoc/desc_pass.rs
@@ -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, 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, 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)
+ }
+}
\ No newline at end of file
diff --git a/src/rustdoc/desc_to_brief_pass.rs b/src/rustdoc/desc_to_brief_pass.rs
index 2ab9a86db4ad..315138db3d32 100644
--- a/src/rustdoc/desc_to_brief_pass.rs
+++ b/src/rustdoc/desc_to_brief_pass.rs
@@ -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,
desc: option
diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs
index 13c618c685b2..9370ffb6c514 100644
--- a/src/rustdoc/doc.rs
+++ b/src/rustdoc/doc.rs
@@ -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
};
+type impldoc = {
+ id: ast_id,
+ name: str,
+ brief: option,
+ desc: option,
+ iface_ty: option,
+ self_ty: option,
+ 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 }
}
}
}
diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs
index 64e179c78c03..a36536fd3e8d 100644
--- a/src/rustdoc/extract.rs
+++ b/src/rustdoc/extract.rs
@@ -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;
}
diff --git a/src/rustdoc/fold.rs b/src/rustdoc/fold.rs
index 6851299db87d..ba5283bd6ff4 100644
--- a/src/rustdoc/fold.rs
+++ b/src/rustdoc/fold.rs
@@ -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;
@@ -21,6 +22,7 @@ type fold_const = fn~(fold: fold, doc: doc::constdoc) -> doc::constdoc;
type fold_enum = fn~(fold: fold, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res = fn~(fold: fold, doc: doc::resdoc) -> doc::resdoc;
type fold_iface = fn~(fold: fold, doc: doc::ifacedoc) -> doc::ifacedoc;
+type fold_impl = fn~(fold: fold, doc: doc::impldoc) -> doc::impldoc;
type t = {
ctxt: T,
@@ -30,7 +32,8 @@ type t = {
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
- fold_iface: fold_iface
+ fold_iface: fold_iface,
+ fold_impl: fold_impl
};
@@ -44,7 +47,8 @@ fn mk_fold(
fold_const: fold_const,
fold_enum: fold_enum,
fold_res: fold_res,
- fold_iface: fold_iface
+ fold_iface: fold_iface,
+ fold_impl: fold_impl
) -> fold {
fold({
ctxt: ctxt,
@@ -54,7 +58,8 @@ fn mk_fold(
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(ctxt: T) -> fold {
{|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(
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(
doc
}
+fn default_seq_fold_impl(
+ _fold: fold,
+ doc: doc::impldoc
+) -> doc::impldoc {
+ doc
+}
+
#[test]
fn default_fold_should_produce_same_doc() {
let source = "mod a { fn b() { } mod c { fn d() { } } }";
diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs
index 0833b5c7e74d..4aab41e38ccc 100644
--- a/src/rustdoc/markdown_pass.rs
+++ b/src/rustdoc/markdown_pass.rs
@@ -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 {
diff --git a/src/rustdoc/prune_undoc_pass.rs b/src/rustdoc/prune_undoc_pass.rs
index a68477058c1f..5b197b9859a9 100644
--- a/src/rustdoc/prune_undoc_pass.rs
+++ b/src/rustdoc/prune_undoc_pass.rs
@@ -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, 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, 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;
-}
\ No newline at end of file
+}
+
+fn fold_impl(
+ fold: fold::fold,
+ 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)
+ }
+}
diff --git a/src/rustdoc/prune_unexported_pass.rs b/src/rustdoc/prune_unexported_pass.rs
index 554124f6348d..94e7332e2ccd 100644
--- a/src/rustdoc/prune_unexported_pass.rs
+++ b/src/rustdoc/prune_unexported_pass.rs
@@ -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)
+ }
+}
\ No newline at end of file
diff --git a/src/rustdoc/trim_pass.rs b/src/rustdoc/trim_pass.rs
index f315be73c59b..bec08afdbd2b 100644
--- a/src/rustdoc/trim_pass.rs
+++ b/src/rustdoc/trim_pass.rs
@@ -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)
+ }
+}
\ No newline at end of file
diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs
index ecf3049b156a..604e411dde07 100644
--- a/src/rustdoc/tystr_pass.rs
+++ b/src/rustdoc/tystr_pass.rs
@@ -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 {
#[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 {
#[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,
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,
+ 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)
+ }
+}
\ No newline at end of file