rustdoc: Split the pruning of undocumented branches into two passes

prune_undoc_details_pass strips arguments and return values that are
undocumented. prune_undoc_items_pass prunes entire items.
This commit is contained in:
Brian Anderson 2012-01-31 21:52:30 -08:00
parent e204aa281d
commit f6f3d518e6
4 changed files with 187 additions and 104 deletions

View File

@ -0,0 +1,162 @@
#[doc = "Prunes args, retvals of the document tree that \
contain no documentation"];
export mk_pass;
fn mk_pass() -> pass {
run
}
fn run(
_srv: astsrv::srv,
doc: doc::cratedoc
) -> doc::cratedoc {
let fold = fold::fold({
fold_fn: fold_fn,
fold_res: fold_res,
fold_iface: fold_iface,
fold_impl: fold_impl
with *fold::default_seq_fold(())
});
fold.fold_crate(fold, doc)
}
fn fold_fn(
fold: fold::fold<()>,
doc: doc::fndoc
) -> doc::fndoc {
let doc = fold::default_seq_fold_fn(fold, doc);
{
args: prune_args(doc.args),
return: prune_return(doc.return)
with doc
}
}
fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
vec::filter_map(docs) {|doc|
if option::is_some(doc.desc) {
some(doc)
} else {
none
}
}
}
fn prune_return(doc: doc::retdoc) -> doc::retdoc {
{
ty: if option::is_some(doc.desc) {
doc.ty
} else {
none
}
with doc
}
}
#[test]
fn should_elide_undocumented_arguments() {
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
assert vec::is_empty(doc.topmod.fns()[0].args);
}
#[test]
fn should_elide_undocumented_return_values() {
let source = "#[doc = \"fonz\"] fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = tystr_pass::mk_pass()(srv, doc);
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
assert doc.topmod.fns()[0].return.ty == none;
}
fn fold_res(
fold: fold::fold<()>,
doc: doc::resdoc
) -> doc::resdoc {
let doc = fold::default_seq_fold_res(fold, doc);
{
args: prune_args(doc.args)
with doc
}
}
#[test]
fn should_elide_undocumented_resource_args() {
let doc = test::mk_doc("#[doc = \"drunk\"]\
resource r(a: bool) { }");
assert vec::is_empty(doc.topmod.resources()[0].args);
}
fn fold_iface(
fold: fold::fold<()>,
doc: doc::ifacedoc
) -> doc::ifacedoc {
let doc = fold::default_seq_fold_iface(fold, doc);
{
methods: prune_methods(doc.methods)
with doc
}
}
fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
vec::map(docs) {|doc|
{
args: prune_args(doc.args),
return: prune_return(doc.return)
with doc
}
}
}
#[test]
fn should_elide_undocumented_iface_method_args() {
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
assert vec::is_empty(doc.topmod.ifaces()[0].methods[0].args);
}
#[test]
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<()>,
doc: doc::impldoc
) -> doc::impldoc {
let doc = fold::default_seq_fold_impl(fold, doc);
{
methods: prune_methods(doc.methods)
with doc
}
}
#[test]
fn should_elide_undocumented_impl_method_args() {
let doc = test::mk_doc(
"#[doc = \"hey\"] impl i for int { fn a(b: bool) { } }");
assert vec::is_empty(doc.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

@ -1,4 +1,4 @@
#[doc = "Prunes branches of the document tree that contain no documentation"];
#[doc = "Prunes items of the document tree that contain no documentation"];
export mk_pass;
@ -109,46 +109,27 @@ fn fold_fn(
fold: fold::fold<ctxt>,
doc: doc::fndoc
) -> doc::fndoc {
let doc = {
args: prune_args(doc.args),
return: prune_return(doc.return)
with doc
};
let doc = fold::default_seq_fold_fn(fold, doc);
fold.ctxt.have_docs =
doc.brief != none
|| doc.desc != none
|| vec::is_not_empty(doc.args)
|| args_have_docs(doc.args)
|| doc.return.desc != none
|| doc.failure != none;
ret doc;
}
fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
vec::filter_map(docs) {|doc|
if option::is_some(doc.desc) {
some(doc)
} else {
none
}
}
}
fn prune_return(doc: doc::retdoc) -> doc::retdoc {
{
ty: if option::is_some(doc.desc) {
doc.ty
} else {
none
}
with doc
fn args_have_docs(docs: [doc::argdoc]) -> bool {
vec::foldl(false, docs) {|accum, doc|
accum || doc.desc != none
}
}
#[test]
fn should_elide_undocumented_arguments() {
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
assert vec::is_empty(doc.topmod.fns()[0].args);
fn should_elide_fns_with_undocumented_arguments() {
let doc = test::mk_doc("fn a(a: int) { }");
assert vec::is_empty(doc.topmod.fns());
}
#[test]
@ -157,17 +138,6 @@ fn should_not_elide_fns_with_documented_arguments() {
assert vec::is_not_empty(doc.topmod.fns());
}
#[test]
fn should_elide_undocumented_return_values() {
let source = "#[doc = \"fonz\"] fn a() -> int { }";
let srv = astsrv::mk_srv_from_str(source);
let doc = extract::from_srv(srv, "");
let doc = tystr_pass::mk_pass()(srv, doc);
let doc = attr_pass::mk_pass()(srv, doc);
let doc = run(srv, doc);
assert doc.topmod.fns()[0].return.ty == none;
}
#[test]
fn should_not_elide_fns_with_documented_failure_conditions() {
let doc = test::mk_doc("#[doc(failure = \"yup\")] fn a() { }");
@ -252,20 +222,12 @@ fn should_not_elide_enums_with_documented_variants() {
}
fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
let doc = {
args: vec::filter_map(doc.args) {|arg|
if arg.desc != none {
some(arg)
} else {
none
}
}
with fold::default_seq_fold_res(fold, doc)
};
let doc = fold::default_seq_fold_res(fold, doc);
fold.ctxt.have_docs =
doc.brief != none
|| doc.desc != none
|| vec::is_not_empty(doc.args);
|| args_have_docs(doc.args);
ret doc;
}
@ -275,13 +237,6 @@ fn should_elide_undocumented_resources() {
assert vec::is_empty(doc.topmod.resources());
}
#[test]
fn should_elide_undocumented_resource_args() {
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 doc = test::mk_doc("#[doc(args(a = \"drunk\"))]\
@ -294,10 +249,7 @@ fn fold_iface(
doc: doc::ifacedoc
) -> doc::ifacedoc {
let doc = fold::default_seq_fold_iface(fold, doc);
let doc = {
methods: prune_methods(doc.methods)
with doc
};
fold.ctxt.have_docs =
doc.brief != none
|| doc.desc != none
@ -305,22 +257,12 @@ fn fold_iface(
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)
|| args_have_docs(doc.args)
|| doc.return.desc != none
|| doc.failure != none
}
@ -338,6 +280,12 @@ fn should_not_elide_documented_ifaces() {
assert vec::is_not_empty(doc.topmod.ifaces());
}
#[test]
fn should_elide_ifaces_with_undocumented_args() {
let doc = test::mk_doc("iface i { fn a(b: bool); }");
assert vec::is_empty(doc.topmod.ifaces());
}
#[test]
fn should_not_elide_ifaces_with_documented_methods() {
let doc = test::mk_doc("iface i { #[doc = \"hey\"] fn a(); }");
@ -350,27 +298,12 @@ fn should_not_elide_undocumented_iface_methods() {
assert vec::is_not_empty(doc.topmod.ifaces()[0].methods);
}
#[test]
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_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
@ -402,20 +335,6 @@ fn should_not_elide_undocumented_impl_methods() {
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 {

View File

@ -21,7 +21,8 @@ mod fold;
mod path_pass;
mod attr_pass;
mod tystr_pass;
mod prune_undoc_pass;
mod prune_undoc_details_pass;
mod prune_undoc_items_pass;
mod prune_unexported_pass;
mod desc_to_brief_pass;
mod desc_pass;

View File

@ -100,8 +100,9 @@ fn run(source_file: str) {
tystr_pass::mk_pass(),
path_pass::mk_pass(),
attr_pass::mk_pass(),
prune_undoc_details_pass::mk_pass(),
// FIXME: This pass should be optional
prune_undoc_pass::mk_pass(),
// prune_undoc_items_pass::mk_pass(),
desc_to_brief_pass::mk_pass(),
trim_pass::mk_pass(),
unindent_pass::mk_pass(),