2012-03-09 13:47:31 -06:00
|
|
|
#[doc = "Breaks rustdocs into sections according to their headers"];
|
|
|
|
|
|
|
|
export mk_pass;
|
|
|
|
|
|
|
|
fn mk_pass() -> pass {
|
|
|
|
{
|
|
|
|
name: "sectionalize",
|
|
|
|
f: run
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run(_srv: astsrv::srv, doc: doc::doc) -> doc::doc {
|
|
|
|
let fold = fold::fold({
|
|
|
|
fold_item: fold_item,
|
|
|
|
fold_iface: fold_iface,
|
|
|
|
fold_impl: fold_impl
|
|
|
|
with *fold::default_any_fold(())
|
|
|
|
});
|
|
|
|
fold.fold_doc(fold, doc)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_item(fold: fold::fold<()>, doc: doc::itemdoc) -> doc::itemdoc {
|
|
|
|
let doc = fold::default_seq_fold_item(fold, doc);
|
|
|
|
let (desc, sections) = sectionalize(doc.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
|
|
|
sections: sections
|
|
|
|
with doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_iface(fold: fold::fold<()>, doc: doc::ifacedoc) -> doc::ifacedoc {
|
|
|
|
let doc = fold::default_seq_fold_iface(fold, doc);
|
|
|
|
|
|
|
|
{
|
|
|
|
methods: par::anymap(doc.methods) {|method|
|
|
|
|
let (desc, sections) = sectionalize(method.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
|
|
|
sections: sections
|
|
|
|
with method
|
|
|
|
}
|
|
|
|
}
|
|
|
|
with doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_impl(fold: fold::fold<()>, doc: doc::impldoc) -> doc::impldoc {
|
|
|
|
let doc = fold::default_seq_fold_impl(fold, doc);
|
|
|
|
|
|
|
|
{
|
|
|
|
methods: par::anymap(doc.methods) {|method|
|
|
|
|
let (desc, sections) = sectionalize(method.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
|
|
|
sections: sections
|
|
|
|
with method
|
|
|
|
}
|
|
|
|
}
|
|
|
|
with doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn sectionalize(desc: option<str>) -> (option<str>, [doc::section]) {
|
|
|
|
|
|
|
|
#[doc = "
|
|
|
|
|
|
|
|
Take a description of the form
|
|
|
|
|
|
|
|
General text
|
|
|
|
|
|
|
|
# Section header
|
|
|
|
|
|
|
|
Section text
|
|
|
|
|
|
|
|
# Section header
|
|
|
|
|
|
|
|
Section text
|
|
|
|
|
|
|
|
and remove each header and accompanying text into section records.
|
|
|
|
|
|
|
|
"];
|
|
|
|
|
|
|
|
if option::is_none(desc) {
|
|
|
|
ret (none, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
let lines = str::lines(option::get(desc));
|
|
|
|
|
2012-03-22 22:06:01 -05:00
|
|
|
let mut new_desc = none::<str>;
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut current_section = none;
|
|
|
|
let mut sections = [];
|
2012-03-09 13:47:31 -06:00
|
|
|
|
2012-04-06 13:01:43 -05:00
|
|
|
for lines.each {|line|
|
2012-03-09 13:47:31 -06:00
|
|
|
alt parse_header(line) {
|
|
|
|
some(header) {
|
|
|
|
if option::is_some(current_section) {
|
|
|
|
sections += [option::get(current_section)];
|
|
|
|
}
|
|
|
|
current_section = some({
|
|
|
|
header: header,
|
|
|
|
body: ""
|
|
|
|
});
|
|
|
|
}
|
|
|
|
none {
|
|
|
|
alt current_section {
|
|
|
|
some(section) {
|
|
|
|
current_section = some({
|
|
|
|
body: section.body + "\n" + line
|
|
|
|
with section
|
|
|
|
});
|
|
|
|
}
|
|
|
|
none {
|
|
|
|
alt new_desc {
|
|
|
|
some(desc) {
|
|
|
|
new_desc = some(desc + "\n" + line);
|
|
|
|
}
|
|
|
|
none {
|
|
|
|
new_desc = some(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if option::is_some(current_section) {
|
|
|
|
sections += [option::get(current_section)];
|
|
|
|
}
|
|
|
|
|
|
|
|
(new_desc, sections)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_header(line: str) -> option<str> {
|
|
|
|
if str::starts_with(line, "# ") {
|
|
|
|
some(str::slice(line, 2u, str::len(line)))
|
|
|
|
} else {
|
|
|
|
none
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_create_section_headers() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
mod a { }");
|
|
|
|
assert str::contains(
|
|
|
|
doc.cratemod().mods()[0].item.sections[0].header,
|
|
|
|
"Header");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_create_section_bodies() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
mod a { }");
|
|
|
|
assert str::contains(
|
|
|
|
doc.cratemod().mods()[0].item.sections[0].body,
|
|
|
|
"Body");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_create_sections_from_indented_headers() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"#[doc = \"\n\
|
|
|
|
Text\n # Header\n\
|
|
|
|
Body\"]\
|
|
|
|
mod a { }");
|
|
|
|
assert vec::is_empty(doc.cratemod().mods()[0].item.sections);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_remove_section_text_from_main_desc() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"#[doc = \"\
|
|
|
|
Description\n\n\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
mod a { }");
|
|
|
|
assert !str::contains(
|
|
|
|
option::get(doc.cratemod().mods()[0].desc()),
|
|
|
|
"Header");
|
|
|
|
assert !str::contains(
|
|
|
|
option::get(doc.cratemod().mods()[0].desc()),
|
|
|
|
"Body");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_eliminate_desc_if_it_is_just_whitespace() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
mod a { }");
|
|
|
|
assert doc.cratemod().mods()[0].desc() == none;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_sectionalize_iface_methods() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"iface i {
|
|
|
|
#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
fn a(); }");
|
|
|
|
assert doc.cratemod().ifaces()[0].methods[0].sections.len() == 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_sectionalize_impl_methods() {
|
|
|
|
let doc = test::mk_doc(
|
|
|
|
"impl i for bool {
|
|
|
|
#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
fn a() { } }");
|
|
|
|
assert doc.cratemod().impls()[0].methods[0].sections.len() == 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
fn mk_doc(source: str) -> doc::doc {
|
|
|
|
astsrv::from_str(source) {|srv|
|
|
|
|
let doc = extract::from_srv(srv, "");
|
|
|
|
let doc = attr_pass::mk_pass().f(srv, doc);
|
|
|
|
run(srv, doc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|