2012-07-04 23:53:12 +02:00
|
|
|
//! Breaks rustdocs into sections according to their headers
|
2012-03-09 20:47:31 +01:00
|
|
|
|
2012-09-19 01:48:40 +02:00
|
|
|
use doc::ItemUtils;
|
2012-07-12 00:00:40 +02:00
|
|
|
|
2012-11-20 03:00:12 +01:00
|
|
|
pub fn mk_pass() -> Pass {
|
2012-03-09 20:47:31 +01:00
|
|
|
{
|
2012-07-14 07:57:48 +02:00
|
|
|
name: ~"sectionalize",
|
2012-03-09 20:47:31 +01:00
|
|
|
f: run
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-20 03:48:46 +01:00
|
|
|
fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
|
2012-09-19 01:48:40 +02:00
|
|
|
let fold = fold::Fold({
|
2012-03-09 20:47:31 +01:00
|
|
|
fold_item: fold_item,
|
2012-07-04 01:30:42 +02:00
|
|
|
fold_trait: fold_trait,
|
2012-09-04 22:29:32 +02:00
|
|
|
fold_impl: fold_impl,
|
|
|
|
.. *fold::default_any_fold(())
|
2012-03-09 20:47:31 +01:00
|
|
|
});
|
2012-11-30 02:51:16 +01:00
|
|
|
(fold.fold_doc)(&fold, doc)
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
2012-11-20 03:48:46 +01:00
|
|
|
fn fold_item(fold: &fold::Fold<()>, +doc: doc::ItemDoc) -> doc::ItemDoc {
|
2012-03-09 20:47:31 +01:00
|
|
|
let doc = fold::default_seq_fold_item(fold, doc);
|
|
|
|
let (desc, sections) = sectionalize(doc.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
2012-09-04 22:29:32 +02:00
|
|
|
sections: sections,
|
|
|
|
.. doc
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-20 03:48:46 +01:00
|
|
|
fn fold_trait(fold: &fold::Fold<()>, +doc: doc::TraitDoc) -> doc::TraitDoc {
|
2012-07-04 01:30:42 +02:00
|
|
|
let doc = fold::default_seq_fold_trait(fold, doc);
|
2012-03-09 20:47:31 +01:00
|
|
|
|
|
|
|
{
|
2012-07-13 19:36:35 +02:00
|
|
|
methods: do par::map(doc.methods) |method| {
|
2012-03-09 20:47:31 +01:00
|
|
|
let (desc, sections) = sectionalize(method.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
2012-09-04 22:29:32 +02:00
|
|
|
sections: sections,
|
2012-09-29 02:17:20 +02:00
|
|
|
.. *method
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
2012-09-04 22:29:32 +02:00
|
|
|
},
|
|
|
|
.. doc
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-20 03:48:46 +01:00
|
|
|
fn fold_impl(fold: &fold::Fold<()>, +doc: doc::ImplDoc) -> doc::ImplDoc {
|
2012-03-09 20:47:31 +01:00
|
|
|
let doc = fold::default_seq_fold_impl(fold, doc);
|
|
|
|
|
|
|
|
{
|
2012-07-13 19:36:35 +02:00
|
|
|
methods: do par::map(doc.methods) |method| {
|
2012-03-09 20:47:31 +01:00
|
|
|
let (desc, sections) = sectionalize(method.desc);
|
|
|
|
|
|
|
|
{
|
|
|
|
desc: desc,
|
2012-09-04 22:29:32 +02:00
|
|
|
sections: sections,
|
2012-09-29 02:17:20 +02:00
|
|
|
.. *method
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
2012-09-04 22:29:32 +02:00
|
|
|
},
|
|
|
|
.. doc
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-19 01:48:40 +02:00
|
|
|
fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {
|
2012-03-09 20:47:31 +01:00
|
|
|
|
2012-07-04 23:53:12 +02:00
|
|
|
/*!
|
|
|
|
* 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.
|
|
|
|
*/
|
2012-03-09 20:47:31 +01:00
|
|
|
|
2012-09-22 04:37:57 +02:00
|
|
|
if desc.is_none() {
|
2012-08-20 21:23:37 +02:00
|
|
|
return (None, ~[]);
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
2012-09-22 04:37:57 +02:00
|
|
|
let lines = str::lines(desc.get());
|
2012-03-09 20:47:31 +01:00
|
|
|
|
2012-08-20 21:23:37 +02:00
|
|
|
let mut new_desc = None::<~str>;
|
|
|
|
let mut current_section = None;
|
2012-06-30 01:26:56 +02:00
|
|
|
let mut sections = ~[];
|
2012-03-09 20:47:31 +01:00
|
|
|
|
2012-07-01 01:19:07 +02:00
|
|
|
for lines.each |line| {
|
2012-09-20 01:55:01 +02:00
|
|
|
match parse_header(*line) {
|
2012-08-20 21:23:37 +02:00
|
|
|
Some(header) => {
|
2012-09-22 04:37:57 +02:00
|
|
|
if current_section.is_some() {
|
|
|
|
sections += ~[current_section.get()];
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
2012-08-20 21:23:37 +02:00
|
|
|
current_section = Some({
|
2012-03-09 20:47:31 +01:00
|
|
|
header: header,
|
2012-07-14 07:57:48 +02:00
|
|
|
body: ~""
|
2012-03-09 20:47:31 +01:00
|
|
|
});
|
|
|
|
}
|
2012-08-20 21:23:37 +02:00
|
|
|
None => {
|
2012-08-06 21:34:08 +02:00
|
|
|
match copy current_section {
|
2012-08-20 21:23:37 +02:00
|
|
|
Some(section) => {
|
|
|
|
current_section = Some({
|
2012-09-20 01:55:01 +02:00
|
|
|
body: section.body + ~"\n" + *line,
|
2012-09-04 22:29:32 +02:00
|
|
|
.. section
|
2012-03-09 20:47:31 +01:00
|
|
|
});
|
|
|
|
}
|
2012-08-20 21:23:37 +02:00
|
|
|
None => {
|
2012-08-06 21:34:08 +02:00
|
|
|
new_desc = match new_desc {
|
2012-08-20 21:23:37 +02:00
|
|
|
Some(desc) => {
|
2012-09-20 01:55:01 +02:00
|
|
|
Some(desc + ~"\n" + *line)
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
2012-08-20 21:23:37 +02:00
|
|
|
None => {
|
2012-09-20 01:55:01 +02:00
|
|
|
Some(*line)
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
2012-05-30 01:33:48 +02:00
|
|
|
};
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-22 04:37:57 +02:00
|
|
|
if current_section.is_some() {
|
|
|
|
sections += ~[current_section.get()];
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
(new_desc, sections)
|
|
|
|
}
|
|
|
|
|
2012-08-20 21:23:37 +02:00
|
|
|
fn parse_header(line: ~str) -> Option<~str> {
|
2012-07-14 07:57:48 +02:00
|
|
|
if str::starts_with(line, ~"# ") {
|
2012-08-20 21:23:37 +02:00
|
|
|
Some(str::slice(line, 2u, str::len(line)))
|
2012-03-09 20:47:31 +01:00
|
|
|
} else {
|
2012-08-20 21:23:37 +02:00
|
|
|
None
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_create_section_headers() {
|
|
|
|
let doc = test::mk_doc(
|
2012-07-14 07:57:48 +02:00
|
|
|
~"#[doc = \"\
|
2012-03-09 20:47:31 +01:00
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
2012-09-22 03:10:45 +02:00
|
|
|
mod a {
|
|
|
|
#[legacy_exports]; }");
|
2012-03-09 20:47:31 +01:00
|
|
|
assert str::contains(
|
|
|
|
doc.cratemod().mods()[0].item.sections[0].header,
|
2012-07-14 07:57:48 +02:00
|
|
|
~"Header");
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_create_section_bodies() {
|
|
|
|
let doc = test::mk_doc(
|
2012-07-14 07:57:48 +02:00
|
|
|
~"#[doc = \"\
|
2012-03-09 20:47:31 +01:00
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
2012-09-22 03:10:45 +02:00
|
|
|
mod a {
|
|
|
|
#[legacy_exports]; }");
|
2012-03-09 20:47:31 +01:00
|
|
|
assert str::contains(
|
|
|
|
doc.cratemod().mods()[0].item.sections[0].body,
|
2012-07-14 07:57:48 +02:00
|
|
|
~"Body");
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_create_sections_from_indented_headers() {
|
|
|
|
let doc = test::mk_doc(
|
2012-07-14 07:57:48 +02:00
|
|
|
~"#[doc = \"\n\
|
2012-03-09 20:47:31 +01:00
|
|
|
Text\n # Header\n\
|
|
|
|
Body\"]\
|
2012-09-22 03:10:45 +02:00
|
|
|
mod a {
|
|
|
|
#[legacy_exports]; }");
|
2012-03-09 20:47:31 +01:00
|
|
|
assert vec::is_empty(doc.cratemod().mods()[0].item.sections);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_remove_section_text_from_main_desc() {
|
|
|
|
let doc = test::mk_doc(
|
2012-07-14 07:57:48 +02:00
|
|
|
~"#[doc = \"\
|
2012-03-09 20:47:31 +01:00
|
|
|
Description\n\n\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
2012-09-22 03:10:45 +02:00
|
|
|
mod a {
|
|
|
|
#[legacy_exports]; }");
|
2012-03-09 20:47:31 +01:00
|
|
|
assert !str::contains(
|
2012-09-22 04:37:57 +02:00
|
|
|
doc.cratemod().mods()[0].desc().get(),
|
2012-07-14 07:57:48 +02:00
|
|
|
~"Header");
|
2012-03-09 20:47:31 +01:00
|
|
|
assert !str::contains(
|
2012-09-22 04:37:57 +02:00
|
|
|
doc.cratemod().mods()[0].desc().get(),
|
2012-07-14 07:57:48 +02:00
|
|
|
~"Body");
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_eliminate_desc_if_it_is_just_whitespace() {
|
|
|
|
let doc = test::mk_doc(
|
2012-07-14 07:57:48 +02:00
|
|
|
~"#[doc = \"\
|
2012-03-09 20:47:31 +01:00
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
2012-09-22 03:10:45 +02:00
|
|
|
mod a {
|
|
|
|
#[legacy_exports]; }");
|
2012-08-20 21:23:37 +02:00
|
|
|
assert doc.cratemod().mods()[0].desc() == None;
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-04 01:30:42 +02:00
|
|
|
fn should_sectionalize_trait_methods() {
|
2012-03-09 20:47:31 +01:00
|
|
|
let doc = test::mk_doc(
|
2012-07-31 19:27:51 +02:00
|
|
|
~"trait i {
|
2012-03-09 20:47:31 +01:00
|
|
|
#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
fn a(); }");
|
2012-07-04 01:30:42 +02:00
|
|
|
assert doc.cratemod().traits()[0].methods[0].sections.len() == 1u;
|
2012-03-09 20:47:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_sectionalize_impl_methods() {
|
|
|
|
let doc = test::mk_doc(
|
2012-08-09 02:19:06 +02:00
|
|
|
~"impl bool {
|
2012-03-09 20:47:31 +01:00
|
|
|
#[doc = \"\
|
|
|
|
# Header\n\
|
|
|
|
Body\"]\
|
|
|
|
fn a() { } }");
|
|
|
|
assert doc.cratemod().impls()[0].methods[0].sections.len() == 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2012-09-22 03:10:45 +02:00
|
|
|
#[legacy_exports];
|
2012-09-19 01:48:40 +02:00
|
|
|
fn mk_doc(source: ~str) -> doc::Doc {
|
2012-07-01 01:19:07 +02:00
|
|
|
do astsrv::from_str(source) |srv| {
|
2012-07-14 07:57:48 +02:00
|
|
|
let doc = extract::from_srv(srv, ~"");
|
2012-03-09 20:47:31 +01:00
|
|
|
let doc = attr_pass::mk_pass().f(srv, doc);
|
|
|
|
run(srv, doc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|