rust/src/librustdoc/page_pass.rs

196 lines
4.4 KiB
Rust
Raw Normal View History

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
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.
*/
use core::prelude::*;
use astsrv;
use config;
2013-03-26 15:38:07 -05:00
use doc::ItemUtils;
use doc;
use fold::Fold;
use fold;
use pass::Pass;
use util::NominalOp;
2013-02-02 05:10:12 -06:00
use core::comm::*;
use syntax::ast;
2013-03-26 15:38:07 -05:00
#[cfg(test)] use doc::PageUtils;
2012-11-19 20:00:12 -06:00
pub fn mk_pass(output_style: config::OutputStyle) -> Pass {
Pass {
name: ~"page",
f: |srv, doc| run(srv, doc, output_style)
}
}
pub fn run(
2012-09-18 18:48:40 -05:00
_srv: astsrv::Srv,
2013-01-30 21:32:36 -06:00
doc: doc::Doc,
2012-09-18 18:48:40 -05:00
output_style: config::OutputStyle
) -> doc::Doc {
2012-09-18 18:48:40 -05:00
if output_style == config::DocPerCrate {
2012-08-01 19:30:05 -05:00
return doc;
}
2013-02-01 02:16:14 -06:00
let (result_port, result_chan) = stream();
let (page_port, page_chan) = stream();
let page_chan = SharedChan(page_chan);
do task::spawn {
result_chan.send(make_doc_from_pages(&page_port));
};
find_pages(doc, page_chan);
2013-02-01 02:16:14 -06:00
result_port.recv()
}
2013-02-01 02:16:14 -06:00
type PagePort = Port<Option<doc::Page>>;
type PageChan = SharedChan<Option<doc::Page>>;
type NominalPageChan = NominalOp<PageChan>;
2013-02-01 02:16:14 -06:00
fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc {
let mut pages = ~[];
loop {
2013-02-01 02:16:14 -06:00
let val = page_port.recv();
2012-09-21 21:37:57 -05:00
if val.is_some() {
pages += ~[val.unwrap()];
} else {
break;
}
}
doc::Doc {
pages: pages
}
}
2013-01-30 21:32:36 -06:00
fn find_pages(doc: doc::Doc, page_chan: PageChan) {
let fold = Fold {
2013-02-01 02:16:14 -06:00
ctxt: NominalOp { op: page_chan.clone() },
fold_crate: fold_crate,
fold_mod: fold_mod,
2012-09-04 15:29:32 -05:00
fold_nmod: fold_nmod,
2013-02-01 02:16:14 -06:00
.. fold::default_any_fold(NominalOp { op: page_chan.clone() })
};
2013-01-30 15:14:35 -06:00
(fold.fold_doc)(&fold, copy doc);
2013-02-01 02:16:14 -06:00
page_chan.send(None);
}
fn fold_crate(
fold: &fold::Fold<NominalPageChan>,
2013-01-30 21:32:36 -06:00
doc: doc::CrateDoc
2012-09-18 18:48:40 -05:00
) -> doc::CrateDoc {
let doc = fold::default_seq_fold_crate(fold, doc);
let page = doc::CratePage(doc::CrateDoc {
2013-01-30 20:52:31 -06:00
topmod: strip_mod(copy doc.topmod),
2013-01-30 15:14:35 -06:00
.. copy doc
});
2013-02-01 02:16:14 -06:00
fold.ctxt.op.send(Some(page));
doc
}
fn fold_mod(
fold: &fold::Fold<NominalPageChan>,
2013-01-30 21:32:36 -06:00
doc: doc::ModDoc
2012-09-18 18:48:40 -05:00
) -> doc::ModDoc {
let doc = fold::default_any_fold_mod(fold, doc);
if doc.id() != ast::crate_node_id {
2013-01-30 20:52:31 -06:00
let doc = strip_mod(copy doc);
2012-09-18 18:48:40 -05:00
let page = doc::ItemPage(doc::ModTag(doc));
2013-02-01 02:16:14 -06:00
fold.ctxt.op.send(Some(page));
}
doc
}
2013-01-30 21:32:36 -06:00
fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
doc::ModDoc {
items: do doc.items.filtered |item| {
2012-09-28 00:20:47 -05:00
match *item {
2012-09-18 18:48:40 -05:00
doc::ModTag(_) => false,
doc::NmodTag(_) => false,
2012-08-03 21:59:04 -05:00
_ => true
}
2012-09-04 15:29:32 -05:00
},
2013-01-30 15:14:35 -06:00
.. copy doc
}
}
fn fold_nmod(
fold: &fold::Fold<NominalPageChan>,
2013-01-30 21:32:36 -06:00
doc: doc::NmodDoc
2012-09-18 18:48:40 -05:00
) -> doc::NmodDoc {
let doc = fold::default_seq_fold_nmod(fold, doc);
2013-01-30 15:14:35 -06:00
let page = doc::ItemPage(doc::NmodTag(copy doc));
2013-02-01 02:16:14 -06:00
fold.ctxt.op.send(Some(page));
2012-08-01 19:30:05 -05:00
return doc;
}
#[cfg(test)]
mod test {
use astsrv;
use config;
use doc;
use extract;
use page_pass::run;
use core::vec;
fn mk_doc_(
2012-09-18 18:48:40 -05:00
output_style: config::OutputStyle,
2013-01-30 21:32:36 -06:00
source: ~str
2012-09-18 18:48:40 -05:00
) -> doc::Doc {
2013-01-30 15:14:35 -06:00
do astsrv::from_str(copy source) |srv| {
2013-01-31 22:24:03 -06:00
let doc = extract::from_srv(srv.clone(), ~"");
run(srv.clone(), doc, output_style)
}
}
fn mk_doc(source: ~str) -> doc::Doc {
2013-01-30 15:14:35 -06:00
mk_doc_(config::DocPerMod, copy source)
}
#[test]
fn should_not_split_the_doc_into_pages_for_doc_per_crate() {
let doc = mk_doc_(
config::DocPerCrate,
~"mod a { } mod b { mod c { } }"
);
assert!(doc.pages.len() == 1u);
}
#[test]
fn should_make_a_page_for_every_mod() {
let doc = mk_doc(~"mod a { }");
assert!(doc.pages.mods()[0].name() == ~"a");
}
#[test]
fn should_remove_mods_from_containing_mods() {
let doc = mk_doc(~"mod a { }");
assert!(vec::is_empty(doc.cratemod().mods()));
}
}