about summary refs log tree commit diff
path: root/src/rustdoc
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-03-06 13:56:33 -0800
committerBrian Anderson <banderson@mozilla.com>2012-03-06 14:48:47 -0800
commitfbd8a76e8a6a4320198c66023e5ec29b3f69cd38 (patch)
tree6842b2f966f151950ee7f894a8324e4a92622be9 /src/rustdoc
parente9b5f4204a113bcbba4819b2ac728c22df113994 (diff)
downloadrust-fbd8a76e8a6a4320198c66023e5ec29b3f69cd38.tar.gz
rust-fbd8a76e8a6a4320198c66023e5ec29b3f69cd38.zip
rustdoc: Add a pass to split the document into pages
Diffstat (limited to 'src/rustdoc')
-rw-r--r--src/rustdoc/doc.rs84
-rw-r--r--src/rustdoc/page_pass.rs152
-rw-r--r--src/rustdoc/rustdoc.rc1
3 files changed, 237 insertions, 0 deletions
diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs
index b7a7fb4dd88..ccee1335835 100644
--- a/src/rustdoc/doc.rs
+++ b/src/rustdoc/doc.rs
@@ -240,6 +240,90 @@ impl util for moddoc {
     }
 }
 
+impl util for [page] {
+
+    fn mods() -> [moddoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(modtag(moddoc)) { some(moddoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn nmods() -> [nmoddoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(nmodtag(nmoddoc)) { some(nmoddoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn fns() -> [fndoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(fntag(fndoc)) { some(fndoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn consts() -> [constdoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(consttag(constdoc)) { some(constdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn enums() -> [enumdoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(enumtag(enumdoc)) { some(enumdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn resources() -> [resdoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(restag(resdoc)) { some(resdoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn ifaces() -> [ifacedoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(ifacetag(ifacedoc)) { some(ifacedoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn impls() -> [impldoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(impltag(impldoc)) { some(impldoc) }
+              _ { none }
+            }
+        }
+    }
+
+    fn types() -> [tydoc] {
+        vec::filter_map(self) {|page|
+            alt page {
+              itempage(tytag(tydoc)) { some(tydoc) }
+              _ { none }
+            }
+        }
+    }
+}
+
 iface item {
     fn item() -> itemdoc;
 }
diff --git a/src/rustdoc/page_pass.rs b/src/rustdoc/page_pass.rs
new file mode 100644
index 00000000000..e3f2c4235e7
--- /dev/null
+++ b/src/rustdoc/page_pass.rs
@@ -0,0 +1,152 @@
+#[doc = "
+
+Divides the document tree into pages.
+
+Each page corresponds is a logical section. There may be pages for individual
+modules, pages for the crate, indexes, etc.
+
+"];
+
+export mk_pass;
+
+fn mk_pass(output_style: config::output_style) -> pass {
+    {
+        name: "page",
+        f: fn~(srv: astsrv::srv, doc: doc::doc) -> doc::doc {
+            run(srv, doc, output_style)
+        }
+    }
+}
+
+fn run(
+    _srv: astsrv::srv,
+    doc: doc::doc,
+    output_style: config::output_style
+) -> doc::doc {
+
+    if output_style == config::doc_per_crate {
+        ret doc;
+    }
+
+    let result_port = comm::port();
+    let result_chan = comm::chan(result_port);
+    let page_chan = task::spawn_listener {|page_port|
+        comm::send(result_chan, make_doc_from_pages(page_port));
+    };
+
+    find_pages(doc, page_chan);
+    comm::recv(result_port)
+}
+
+type page_port = comm::port<option<doc::page>>;
+type page_chan = comm::chan<option<doc::page>>;
+
+fn make_doc_from_pages(page_port: page_port) -> doc::doc {
+    let mut pages = [];
+    while true {
+        let val = comm::recv(page_port);
+        if option::is_some(val) {
+            pages += [option::unwrap(val)];
+        } else {
+            break;
+        }
+    }
+    {
+        pages: pages
+    }
+}
+
+fn find_pages(doc: doc::doc, page_chan: page_chan) {
+    let fold = fold::fold({
+        fold_crate: fold_crate,
+        fold_mod: fold_mod
+        with *fold::default_any_fold(page_chan)
+    });
+    fold.fold_doc(fold, doc);
+
+    comm::send(page_chan, none);
+}
+
+fn fold_crate(
+    fold: fold::fold<page_chan>,
+    doc: doc::cratedoc
+) -> doc::cratedoc {
+
+    let doc = fold::default_seq_fold_crate(fold, doc);
+
+    let page = doc::cratepage({
+        topmod: strip_mod(doc.topmod)
+        with doc
+    });
+
+    comm::send(fold.ctxt, some(page));
+
+    doc
+}
+
+fn fold_mod(
+    fold: fold::fold<page_chan>,
+    doc: doc::moddoc
+) -> doc::moddoc {
+
+    let doc = fold::default_any_fold_mod(fold, doc);
+
+    if doc.id() != rustc::syntax::ast::crate_node_id {
+
+        let doc = strip_mod(doc);
+        let page = doc::itempage(doc::modtag(doc));
+        comm::send(fold.ctxt, some(page));
+    }
+
+    doc
+}
+
+fn strip_mod(doc: doc::moddoc) -> doc::moddoc {
+    {
+        items: vec::filter(doc.items) {|item|
+            alt item {
+              doc::modtag(_) { false }
+              _ { true }
+            }
+        }
+        with doc
+    }
+}
+
+#[test]
+fn should_not_split_the_doc_into_pages_for_doc_per_crate() {
+    let doc = test::mk_doc_(
+        config::doc_per_crate,
+        "mod a { } mod b { mod c { } }"
+    );
+    assert doc.pages.len() == 1u;
+}
+
+#[test]
+fn should_make_a_page_for_every_mod() {
+    let doc = test::mk_doc("mod a { }");
+    assert doc.pages.mods()[0].name() == "a";
+}
+
+#[test]
+fn should_remove_mods_from_containing_mods() {
+    let doc = test::mk_doc("mod a { }");
+    assert vec::is_empty(doc.cratemod().mods());
+}
+
+#[cfg(test)]
+mod test {
+    fn mk_doc_(
+        output_style: config::output_style,
+        source: str
+    ) -> doc::doc {
+        astsrv::from_str(source) {|srv|
+            let doc = extract::from_srv(srv, "");
+            run(srv, doc, output_style)
+        }
+    }
+
+    fn mk_doc(source: str) -> doc::doc {
+        mk_doc_(config::doc_per_mod, source)
+    }
+}
\ No newline at end of file
diff --git a/src/rustdoc/rustdoc.rc b/src/rustdoc/rustdoc.rc
index 69a95cfd24c..c53b11fa021 100644
--- a/src/rustdoc/rustdoc.rc
+++ b/src/rustdoc/rustdoc.rc
@@ -38,3 +38,4 @@ mod sort_item_name_pass;
 mod sort_item_type_pass;
 mod reexport_pass;
 mod par;
+mod page_pass;