// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! The document model pub type AstId = int; pub type Doc_ = { pages: ~[Page] }; impl Doc_ : cmp::Eq { pure fn eq(&self, other: &Doc_) -> bool { (*self).pages == (*other).pages } pure fn ne(&self, other: &Doc_) -> bool { !(*self).eq(other) } } pub enum Doc { Doc_(Doc_) } impl Doc : cmp::Eq { pure fn eq(&self, other: &Doc) -> bool { *(*self) == *(*other) } pure fn ne(&self, other: &Doc) -> bool { *(*self) != *(*other) } } pub enum Page { CratePage(CrateDoc), ItemPage(ItemTag) } impl Page : cmp::Eq { pure fn eq(&self, other: &Page) -> bool { match (*self) { CratePage(e0a) => { match (*other) { CratePage(e0b) => e0a == e0b, _ => false } } ItemPage(e0a) => { match (*other) { ItemPage(e0b) => e0a == e0b, _ => false } } } } pure fn ne(&self, other: &Page) -> bool { !(*self).eq(other) } } pub enum Implementation { Required, Provided, } impl Implementation : cmp::Eq { pure fn eq(&self, other: &Implementation) -> bool { ((*self) as uint) == ((*other) as uint) } pure fn ne(&self, other: &Implementation) -> bool { !(*self).eq(other) } } /** * Most rustdocs can be parsed into 'sections' according to their markdown * headers */ pub type Section = { header: ~str, body: ~str }; impl Section : cmp::Eq { pure fn eq(&self, other: &Section) -> bool { (*self).header == (*other).header && (*self).body == (*other).body } pure fn ne(&self, other: &Section) -> bool { !(*self).eq(other) } } // 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. pub type CrateDoc = { topmod: ModDoc, }; impl CrateDoc : cmp::Eq { pure fn eq(&self, other: &CrateDoc) -> bool { (*self).topmod == (*other).topmod } pure fn ne(&self, other: &CrateDoc) -> bool { !(*self).eq(other) } } pub enum ItemTag { ModTag(ModDoc), NmodTag(NmodDoc), ConstTag(ConstDoc), FnTag(FnDoc), EnumTag(EnumDoc), TraitTag(TraitDoc), ImplTag(ImplDoc), TyTag(TyDoc), StructTag(StructDoc) } impl ItemTag : cmp::Eq { pure fn eq(&self, other: &ItemTag) -> bool { match (*self) { ModTag(e0a) => { match (*other) { ModTag(e0b) => e0a == e0b, _ => false } } NmodTag(e0a) => { match (*other) { NmodTag(e0b) => e0a == e0b, _ => false } } ConstTag(e0a) => { match (*other) { ConstTag(e0b) => e0a == e0b, _ => false } } FnTag(e0a) => { match (*other) { FnTag(e0b) => e0a == e0b, _ => false } } EnumTag(e0a) => { match (*other) { EnumTag(e0b) => e0a == e0b, _ => false } } TraitTag(e0a) => { match (*other) { TraitTag(e0b) => e0a == e0b, _ => false } } ImplTag(e0a) => { match (*other) { ImplTag(e0b) => e0a == e0b, _ => false } } TyTag(e0a) => { match (*other) { TyTag(e0b) => e0a == e0b, _ => false } } StructTag(e0a) => { match (*other) { StructTag(e0b) => e0a == e0b, _ => false } } } } pure fn ne(&self, other: &ItemTag) -> bool { !(*self).eq(other) } } pub type ItemDoc = { id: AstId, 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 }; impl ItemDoc : cmp::Eq { pure fn eq(&self, other: &ItemDoc) -> bool { (*self).id == (*other).id && (*self).name == (*other).name && (*self).path == (*other).path && (*self).brief == (*other).brief && (*self).desc == (*other).desc && (*self).sections == (*other).sections && (*self).reexport == (*other).reexport } pure fn ne(&self, other: &ItemDoc) -> bool { !(*self).eq(other) } } pub type SimpleItemDoc = { item: ItemDoc, sig: Option<~str> }; impl SimpleItemDoc : cmp::Eq { pure fn eq(&self, other: &SimpleItemDoc) -> bool { (*self).item == (*other).item && (*self).sig == (*other).sig } pure fn ne(&self, other: &SimpleItemDoc) -> bool { !(*self).eq(other) } } pub type ModDoc_ = { item: ItemDoc, items: ~[ItemTag], index: Option }; impl ModDoc_ : cmp::Eq { pure fn eq(&self, other: &ModDoc_) -> bool { (*self).item == (*other).item && (*self).items == (*other).items && (*self).index == (*other).index } pure fn ne(&self, other: &ModDoc_) -> bool { !(*self).eq(other) } } pub enum ModDoc { ModDoc_(ModDoc_) } impl ModDoc : cmp::Eq { pure fn eq(&self, other: &ModDoc) -> bool { *(*self) == *(*other) } pure fn ne(&self, other: &ModDoc) -> bool { *(*self) != *(*other) } } pub type NmodDoc = { item: ItemDoc, fns: ~[FnDoc], index: Option }; impl NmodDoc : cmp::Eq { pure fn eq(&self, other: &NmodDoc) -> bool { (*self).item == (*other).item && (*self).fns == (*other).fns && (*self).index == (*other).index } pure fn ne(&self, other: &NmodDoc) -> bool { !(*self).eq(other) } } pub type ConstDoc = SimpleItemDoc; pub type FnDoc = SimpleItemDoc; pub type EnumDoc = { item: ItemDoc, variants: ~[VariantDoc] }; impl EnumDoc : cmp::Eq { pure fn eq(&self, other: &EnumDoc) -> bool { (*self).item == (*other).item && (*self).variants == (*other).variants } pure fn ne(&self, other: &EnumDoc) -> bool { !(*self).eq(other) } } pub type VariantDoc = { name: ~str, desc: Option<~str>, sig: Option<~str> }; impl VariantDoc : cmp::Eq { pure fn eq(&self, other: &VariantDoc) -> bool { (*self).name == (*other).name && (*self).desc == (*other).desc && (*self).sig == (*other).sig } pure fn ne(&self, other: &VariantDoc) -> bool { !(*self).eq(other) } } pub type TraitDoc = { item: ItemDoc, methods: ~[MethodDoc] }; impl TraitDoc : cmp::Eq { pure fn eq(&self, other: &TraitDoc) -> bool { (*self).item == (*other).item && (*self).methods == (*other).methods } pure fn ne(&self, other: &TraitDoc) -> bool { !(*self).eq(other) } } pub type MethodDoc = { name: ~str, brief: Option<~str>, desc: Option<~str>, sections: ~[Section], sig: Option<~str>, implementation: Implementation, }; impl MethodDoc : cmp::Eq { pure fn eq(&self, other: &MethodDoc) -> bool { (*self).name == (*other).name && (*self).brief == (*other).brief && (*self).desc == (*other).desc && (*self).sections == (*other).sections && (*self).sig == (*other).sig && (*self).implementation == (*other).implementation } pure fn ne(&self, other: &MethodDoc) -> bool { !(*self).eq(other) } } pub type ImplDoc = { item: ItemDoc, trait_types: ~[~str], self_ty: Option<~str>, methods: ~[MethodDoc] }; impl ImplDoc : cmp::Eq { pure fn eq(&self, other: &ImplDoc) -> bool { (*self).item == (*other).item && (*self).trait_types == (*other).trait_types && (*self).self_ty == (*other).self_ty && (*self).methods == (*other).methods } pure fn ne(&self, other: &ImplDoc) -> bool { !(*self).eq(other) } } pub type TyDoc = SimpleItemDoc; pub type StructDoc = { item: ItemDoc, fields: ~[~str], sig: Option<~str> }; impl StructDoc : cmp::Eq { pure fn eq(&self, other: &StructDoc) -> bool { return (*self).item == other.item && (*self).fields == other.fields && (*self).sig == other.sig; } pure fn ne(&self, other: &StructDoc) -> bool { !(*self).eq(other) } } pub type Index = { entries: ~[IndexEntry] }; impl Index : cmp::Eq { pure fn eq(&self, other: &Index) -> bool { (*self).entries == (*other).entries } pure fn ne(&self, other: &Index) -> bool { !(*self).eq(other) } } /** * 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 */ pub type IndexEntry = { kind: ~str, name: ~str, brief: Option<~str>, link: ~str }; impl IndexEntry : cmp::Eq { pure fn eq(&self, other: &IndexEntry) -> bool { (*self).kind == (*other).kind && (*self).name == (*other).name && (*self).brief == (*other).brief && (*self).link == (*other).link } pure fn ne(&self, other: &IndexEntry) -> bool { !(*self).eq(other) } } 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 } } } fn structs() -> ~[StructDoc] { do vec::filter_map(self.items) |itemtag| { match *itemtag { StructTag(StructDoc) => Some(StructDoc), _ => None } } } } pub trait PageUtils { fn mods(&self) -> ~[ModDoc]; fn nmods(&self) -> ~[NmodDoc]; fn fns(&self) -> ~[FnDoc]; fn consts(&self) -> ~[ConstDoc]; fn enums(&self) -> ~[EnumDoc]; fn traits(&self) -> ~[TraitDoc]; fn impls(&self) -> ~[ImplDoc]; fn types(&self) -> ~[TyDoc]; } impl ~[Page]: PageUtils { fn mods(&self) -> ~[ModDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(ModTag(ModDoc)) => Some(ModDoc), _ => None } } } fn nmods(&self) -> ~[NmodDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(NmodTag(nModDoc)) => Some(nModDoc), _ => None } } } fn fns(&self) -> ~[FnDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(FnTag(FnDoc)) => Some(FnDoc), _ => None } } } fn consts(&self) -> ~[ConstDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(ConstTag(ConstDoc)) => Some(ConstDoc), _ => None } } } fn enums(&self) -> ~[EnumDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(EnumTag(EnumDoc)) => Some(EnumDoc), _ => None } } } fn traits(&self) -> ~[TraitDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(TraitTag(TraitDoc)) => Some(TraitDoc), _ => None } } } fn impls(&self) -> ~[ImplDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(ImplTag(ImplDoc)) => Some(ImplDoc), _ => None } } } fn types(&self) -> ~[TyDoc] { do vec::filter_map(*self) |page| { match *page { ItemPage(TyTag(TyDoc)) => Some(TyDoc), _ => None } } } } pub trait Item { pure fn item(&self) -> ItemDoc; } impl ItemTag: Item { pure fn item(&self) -> 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, doc::StructTag(doc) => doc.item } } } impl SimpleItemDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl ModDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl NmodDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl EnumDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl TraitDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl ImplDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } impl StructDoc: Item { pure fn item(&self) -> ItemDoc { self.item } } pub trait ItemUtils { pure fn id(&self) -> AstId; pure fn name(&self) -> ~str; pure fn path(&self) -> ~[~str]; pure fn brief(&self) -> Option<~str>; pure fn desc(&self) -> Option<~str>; pure fn sections(&self) -> ~[Section]; } impl A: ItemUtils { pure fn id(&self) -> AstId { self.item().id } pure fn name(&self) -> ~str { self.item().name } pure fn path(&self) -> ~[~str] { self.item().path } pure fn brief(&self) -> Option<~str> { self.item().brief } pure fn desc(&self) -> Option<~str> { self.item().desc } pure fn sections(&self) -> ~[Section] { self.item().sections } }