Skip to content

Commit fbd8a76

Browse files
committed
rustdoc: Add a pass to split the document into pages
1 parent e9b5f42 commit fbd8a76

File tree

3 files changed

+237
-0
lines changed

3 files changed

+237
-0
lines changed

src/rustdoc/doc.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,90 @@ impl util for moddoc {
240240
}
241241
}
242242

243+
impl util for [page] {
244+
245+
fn mods() -> [moddoc] {
246+
vec::filter_map(self) {|page|
247+
alt page {
248+
itempage(modtag(moddoc)) { some(moddoc) }
249+
_ { none }
250+
}
251+
}
252+
}
253+
254+
fn nmods() -> [nmoddoc] {
255+
vec::filter_map(self) {|page|
256+
alt page {
257+
itempage(nmodtag(nmoddoc)) { some(nmoddoc) }
258+
_ { none }
259+
}
260+
}
261+
}
262+
263+
fn fns() -> [fndoc] {
264+
vec::filter_map(self) {|page|
265+
alt page {
266+
itempage(fntag(fndoc)) { some(fndoc) }
267+
_ { none }
268+
}
269+
}
270+
}
271+
272+
fn consts() -> [constdoc] {
273+
vec::filter_map(self) {|page|
274+
alt page {
275+
itempage(consttag(constdoc)) { some(constdoc) }
276+
_ { none }
277+
}
278+
}
279+
}
280+
281+
fn enums() -> [enumdoc] {
282+
vec::filter_map(self) {|page|
283+
alt page {
284+
itempage(enumtag(enumdoc)) { some(enumdoc) }
285+
_ { none }
286+
}
287+
}
288+
}
289+
290+
fn resources() -> [resdoc] {
291+
vec::filter_map(self) {|page|
292+
alt page {
293+
itempage(restag(resdoc)) { some(resdoc) }
294+
_ { none }
295+
}
296+
}
297+
}
298+
299+
fn ifaces() -> [ifacedoc] {
300+
vec::filter_map(self) {|page|
301+
alt page {
302+
itempage(ifacetag(ifacedoc)) { some(ifacedoc) }
303+
_ { none }
304+
}
305+
}
306+
}
307+
308+
fn impls() -> [impldoc] {
309+
vec::filter_map(self) {|page|
310+
alt page {
311+
itempage(impltag(impldoc)) { some(impldoc) }
312+
_ { none }
313+
}
314+
}
315+
}
316+
317+
fn types() -> [tydoc] {
318+
vec::filter_map(self) {|page|
319+
alt page {
320+
itempage(tytag(tydoc)) { some(tydoc) }
321+
_ { none }
322+
}
323+
}
324+
}
325+
}
326+
243327
iface item {
244328
fn item() -> itemdoc;
245329
}

src/rustdoc/page_pass.rs

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#[doc = "
2+
3+
Divides the document tree into pages.
4+
5+
Each page corresponds is a logical section. There may be pages for individual
6+
modules, pages for the crate, indexes, etc.
7+
8+
"];
9+
10+
export mk_pass;
11+
12+
fn mk_pass(output_style: config::output_style) -> pass {
13+
{
14+
name: "page",
15+
f: fn~(srv: astsrv::srv, doc: doc::doc) -> doc::doc {
16+
run(srv, doc, output_style)
17+
}
18+
}
19+
}
20+
21+
fn run(
22+
_srv: astsrv::srv,
23+
doc: doc::doc,
24+
output_style: config::output_style
25+
) -> doc::doc {
26+
27+
if output_style == config::doc_per_crate {
28+
ret doc;
29+
}
30+
31+
let result_port = comm::port();
32+
let result_chan = comm::chan(result_port);
33+
let page_chan = task::spawn_listener {|page_port|
34+
comm::send(result_chan, make_doc_from_pages(page_port));
35+
};
36+
37+
find_pages(doc, page_chan);
38+
comm::recv(result_port)
39+
}
40+
41+
type page_port = comm::port<option<doc::page>>;
42+
type page_chan = comm::chan<option<doc::page>>;
43+
44+
fn make_doc_from_pages(page_port: page_port) -> doc::doc {
45+
let mut pages = [];
46+
while true {
47+
let val = comm::recv(page_port);
48+
if option::is_some(val) {
49+
pages += [option::unwrap(val)];
50+
} else {
51+
break;
52+
}
53+
}
54+
{
55+
pages: pages
56+
}
57+
}
58+
59+
fn find_pages(doc: doc::doc, page_chan: page_chan) {
60+
let fold = fold::fold({
61+
fold_crate: fold_crate,
62+
fold_mod: fold_mod
63+
with *fold::default_any_fold(page_chan)
64+
});
65+
fold.fold_doc(fold, doc);
66+
67+
comm::send(page_chan, none);
68+
}
69+
70+
fn fold_crate(
71+
fold: fold::fold<page_chan>,
72+
doc: doc::cratedoc
73+
) -> doc::cratedoc {
74+
75+
let doc = fold::default_seq_fold_crate(fold, doc);
76+
77+
let page = doc::cratepage({
78+
topmod: strip_mod(doc.topmod)
79+
with doc
80+
});
81+
82+
comm::send(fold.ctxt, some(page));
83+
84+
doc
85+
}
86+
87+
fn fold_mod(
88+
fold: fold::fold<page_chan>,
89+
doc: doc::moddoc
90+
) -> doc::moddoc {
91+
92+
let doc = fold::default_any_fold_mod(fold, doc);
93+
94+
if doc.id() != rustc::syntax::ast::crate_node_id {
95+
96+
let doc = strip_mod(doc);
97+
let page = doc::itempage(doc::modtag(doc));
98+
comm::send(fold.ctxt, some(page));
99+
}
100+
101+
doc
102+
}
103+
104+
fn strip_mod(doc: doc::moddoc) -> doc::moddoc {
105+
{
106+
items: vec::filter(doc.items) {|item|
107+
alt item {
108+
doc::modtag(_) { false }
109+
_ { true }
110+
}
111+
}
112+
with doc
113+
}
114+
}
115+
116+
#[test]
117+
fn should_not_split_the_doc_into_pages_for_doc_per_crate() {
118+
let doc = test::mk_doc_(
119+
config::doc_per_crate,
120+
"mod a { } mod b { mod c { } }"
121+
);
122+
assert doc.pages.len() == 1u;
123+
}
124+
125+
#[test]
126+
fn should_make_a_page_for_every_mod() {
127+
let doc = test::mk_doc("mod a { }");
128+
assert doc.pages.mods()[0].name() == "a";
129+
}
130+
131+
#[test]
132+
fn should_remove_mods_from_containing_mods() {
133+
let doc = test::mk_doc("mod a { }");
134+
assert vec::is_empty(doc.cratemod().mods());
135+
}
136+
137+
#[cfg(test)]
138+
mod test {
139+
fn mk_doc_(
140+
output_style: config::output_style,
141+
source: str
142+
) -> doc::doc {
143+
astsrv::from_str(source) {|srv|
144+
let doc = extract::from_srv(srv, "");
145+
run(srv, doc, output_style)
146+
}
147+
}
148+
149+
fn mk_doc(source: str) -> doc::doc {
150+
mk_doc_(config::doc_per_mod, source)
151+
}
152+
}

src/rustdoc/rustdoc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ mod sort_item_name_pass;
3838
mod sort_item_type_pass;
3939
mod reexport_pass;
4040
mod par;
41+
mod page_pass;

0 commit comments

Comments
 (0)