rust/src/rustdoc/doc.rs
2012-08-08 18:19:24 -07:00

395 lines
7.7 KiB
Rust

//! The document model
type ast_id = int;
type doc_ = {
pages: ~[page]
};
enum doc {
doc_(doc_)
}
enum page {
cratepage(cratedoc),
itempage(itemtag)
}
enum implementation {
required,
provided,
}
/**
* Most rustdocs can be parsed into 'sections' according to their markdown
* headers
*/
type section = {
header: ~str,
body: ~str
};
// FIXME (#2596): We currently give topmod the name of the crate. There
// would probably be fewer special cases if the crate had its own name
// and topmod's name was the empty string.
type cratedoc = {
topmod: moddoc,
};
enum itemtag {
modtag(moddoc),
nmodtag(nmoddoc),
consttag(constdoc),
fntag(fndoc),
enumtag(enumdoc),
traittag(traitdoc),
impltag(impldoc),
tytag(tydoc)
}
type itemdoc = {
id: ast_id,
name: ~str,
path: ~[~str],
brief: option<~str>,
desc: option<~str>,
sections: ~[section],
// Indicates that this node is a reexport of a different item
reexport: bool
};
type simpleitemdoc = {
item: itemdoc,
sig: option<~str>
};
type moddoc_ = {
item: itemdoc,
items: ~[itemtag],
index: option<index>
};
enum moddoc {
moddoc_(moddoc_)
}
type nmoddoc = {
item: itemdoc,
fns: ~[fndoc],
index: option<index>
};
type constdoc = simpleitemdoc;
type fndoc = simpleitemdoc;
type enumdoc = {
item: itemdoc,
variants: ~[variantdoc]
};
type variantdoc = {
name: ~str,
desc: option<~str>,
sig: option<~str>
};
type traitdoc = {
item: itemdoc,
methods: ~[methoddoc]
};
type methoddoc = {
name: ~str,
brief: option<~str>,
desc: option<~str>,
sections: ~[section],
sig: option<~str>,
implementation: implementation,
};
type impldoc = {
item: itemdoc,
trait_types: ~[~str],
self_ty: option<~str>,
methods: ~[methoddoc]
};
type tydoc = simpleitemdoc;
type index = {
entries: ~[index_entry]
};
/**
* A single entry in an index
*
* Fields:
*
* * kind - The type of thing being indexed, e.g. 'Module'
* * name - The name of the thing
* * brief - The brief description
* * link - A format-specific string representing the link target
*/
type index_entry = {
kind: ~str,
name: ~str,
brief: option<~str>,
link: ~str
};
impl doc {
fn cratedoc() -> cratedoc {
option::get(vec::foldl(none, self.pages, |_m, page| {
match page {
doc::cratepage(doc) => some(doc),
_ => none
}
}))
}
fn cratemod() -> moddoc {
self.cratedoc().topmod
}
}
/// Some helper methods on moddoc, mostly for testing
impl moddoc {
fn mods() -> ~[moddoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
modtag(moddoc) => some(moddoc),
_ => none
}
}
}
fn nmods() -> ~[nmoddoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
nmodtag(nmoddoc) => some(nmoddoc),
_ => none
}
}
}
fn fns() -> ~[fndoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
fntag(fndoc) => some(fndoc),
_ => none
}
}
}
fn consts() -> ~[constdoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
consttag(constdoc) => some(constdoc),
_ => none
}
}
}
fn enums() -> ~[enumdoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
enumtag(enumdoc) => some(enumdoc),
_ => none
}
}
}
fn traits() -> ~[traitdoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
traittag(traitdoc) => some(traitdoc),
_ => none
}
}
}
fn impls() -> ~[impldoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
impltag(impldoc) => some(impldoc),
_ => none
}
}
}
fn types() -> ~[tydoc] {
do vec::filter_map(self.items) |itemtag| {
match itemtag {
tytag(tydoc) => some(tydoc),
_ => none
}
}
}
}
trait page_utils {
fn mods() -> ~[moddoc];
fn nmods() -> ~[nmoddoc];
fn fns() -> ~[fndoc];
fn consts() -> ~[constdoc];
fn enums() -> ~[enumdoc];
fn traits() -> ~[traitdoc];
fn impls() -> ~[impldoc];
fn types() -> ~[tydoc];
}
impl ~[page]: page_utils {
fn mods() -> ~[moddoc] {
do vec::filter_map(self) |page| {
match page {
itempage(modtag(moddoc)) => some(moddoc),
_ => none
}
}
}
fn nmods() -> ~[nmoddoc] {
do vec::filter_map(self) |page| {
match page {
itempage(nmodtag(nmoddoc)) => some(nmoddoc),
_ => none
}
}
}
fn fns() -> ~[fndoc] {
do vec::filter_map(self) |page| {
match page {
itempage(fntag(fndoc)) => some(fndoc),
_ => none
}
}
}
fn consts() -> ~[constdoc] {
do vec::filter_map(self) |page| {
match page {
itempage(consttag(constdoc)) => some(constdoc),
_ => none
}
}
}
fn enums() -> ~[enumdoc] {
do vec::filter_map(self) |page| {
match page {
itempage(enumtag(enumdoc)) => some(enumdoc),
_ => none
}
}
}
fn traits() -> ~[traitdoc] {
do vec::filter_map(self) |page| {
match page {
itempage(traittag(traitdoc)) => some(traitdoc),
_ => none
}
}
}
fn impls() -> ~[impldoc] {
do vec::filter_map(self) |page| {
match page {
itempage(impltag(impldoc)) => some(impldoc),
_ => none
}
}
}
fn types() -> ~[tydoc] {
do vec::filter_map(self) |page| {
match page {
itempage(tytag(tydoc)) => some(tydoc),
_ => none
}
}
}
}
trait item {
pure fn item() -> itemdoc;
}
impl itemtag: item {
pure fn item() -> itemdoc {
match self {
doc::modtag(doc) => doc.item,
doc::nmodtag(doc) => doc.item,
doc::fntag(doc) => doc.item,
doc::consttag(doc) => doc.item,
doc::enumtag(doc) => doc.item,
doc::traittag(doc) => doc.item,
doc::impltag(doc) => doc.item,
doc::tytag(doc) => doc.item
}
}
}
impl simpleitemdoc: item {
pure fn item() -> itemdoc { self.item }
}
impl moddoc: item {
pure fn item() -> itemdoc { self.item }
}
impl nmoddoc: item {
pure fn item() -> itemdoc { self.item }
}
impl enumdoc: item {
pure fn item() -> itemdoc { self.item }
}
impl traitdoc: item {
pure fn item() -> itemdoc { self.item }
}
impl impldoc: item {
pure fn item() -> itemdoc { self.item }
}
trait item_utils {
pure fn id() -> ast_id;
pure fn name() -> ~str;
pure fn path() -> ~[~str];
pure fn brief() -> option<~str>;
pure fn desc() -> option<~str>;
pure fn sections() -> ~[section];
}
impl<A:item> A: item_utils {
pure fn id() -> ast_id {
self.item().id
}
pure fn name() -> ~str {
self.item().name
}
pure fn path() -> ~[~str] {
self.item().path
}
pure fn brief() -> option<~str> {
self.item().brief
}
pure fn desc() -> option<~str> {
self.item().desc
}
pure fn sections() -> ~[section] {
self.item().sections
}
}