From c6ed447221303be59381f91852e0fcd50f60be06 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 19 Sep 2012 14:37:43 -0700 Subject: [PATCH] rustdoc: Begin support for structs --- src/rustdoc/doc.rs | 40 ++++++++++++++++++++++++++++-- src/rustdoc/extract.rs | 33 ++++++++++++++++++++++++ src/rustdoc/fold.rs | 34 ++++++++++++++++++++----- src/rustdoc/markdown_pass.rs | 20 ++++++++++++++- src/rustdoc/sort_item_type_pass.rs | 25 +++++++++++-------- src/rustdoc/tystr_pass.rs | 27 ++++++++++++++++++++ 6 files changed, 159 insertions(+), 20 deletions(-) diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs index 129c5568979..5d758fd0612 100644 --- a/src/rustdoc/doc.rs +++ b/src/rustdoc/doc.rs @@ -98,7 +98,8 @@ enum ItemTag { EnumTag(EnumDoc), TraitTag(TraitDoc), ImplTag(ImplDoc), - TyTag(TyDoc) + TyTag(TyDoc), + StructTag(StructDoc) } impl ItemTag : cmp::Eq { @@ -152,6 +153,12 @@ impl ItemTag : cmp::Eq { _ => false } } + StructTag(e0a) => { + match other { + StructTag(e0b) => e0a == e0b, + _ => false + } + } } } pure fn ne(&&other: ItemTag) -> bool { !self.eq(other) } @@ -315,6 +322,21 @@ impl ImplDoc : cmp::Eq { type TyDoc = SimpleItemDoc; +type StructDoc = { + item: ItemDoc, + fields: ~[~str], + sig: Option<~str> +}; + +impl StructDoc : cmp::Eq { + pure fn eq(&&other: StructDoc) -> bool { + return self.item == other.item + && self.fields == other.fields + && self.sig == other.sig; + } + pure fn ne(&&other: StructDoc) -> bool { !self.eq(other) } +} + type Index = { entries: ~[IndexEntry] }; @@ -442,6 +464,15 @@ fn types() -> ~[TyDoc] { } } } + + fn structs() -> ~[StructDoc] { + do vec::filter_map(self.items) |itemtag| { + match itemtag { + StructTag(StructDoc) => Some(StructDoc), + _ => None + } + } + } } trait PageUtils { @@ -544,7 +575,8 @@ impl ItemTag: Item { doc::EnumTag(doc) => doc.item, doc::TraitTag(doc) => doc.item, doc::ImplTag(doc) => doc.item, - doc::TyTag(doc) => doc.item + doc::TyTag(doc) => doc.item, + doc::StructTag(doc) => doc.item } } } @@ -573,6 +605,10 @@ impl ImplDoc: Item { pure fn item() -> ItemDoc { self.item } } +impl StructDoc: Item { + pure fn item() -> ItemDoc { self.item } +} + trait ItemUtils { pure fn id() -> AstId; pure fn name() -> ~str; diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs index 2cce6655542..c35f59864f6 100644 --- a/src/rustdoc/extract.rs +++ b/src/rustdoc/extract.rs @@ -119,6 +119,11 @@ fn moddoc_from_mod( tydoc_from_ty(ItemDoc) )) } + ast::item_class(def, _) => { + Some(doc::StructTag( + structdoc_from_struct(ItemDoc, def) + )) + } _ => None } }, @@ -293,6 +298,34 @@ fn should_extract_tys() { assert doc.cratemod().types()[0].name() == ~"a"; } +fn structdoc_from_struct( + itemdoc: doc::ItemDoc, + struct_def: @ast::struct_def +) -> doc::StructDoc { + { + item: itemdoc, + fields: do struct_def.fields.map |field| { + match field.node.kind { + ast::named_field(ident, _, _) => to_str(ident), + ast::unnamed_field => fail ~"what is an unnamed struct field?" + } + }, + sig: None + } +} + +#[test] +fn should_extract_structs() { + let doc = test::mk_doc(~"struct Foo { field: () }"); + assert doc.cratemod().structs()[0].name() == ~"Foo"; +} + +#[test] +fn should_extract_struct_fields() { + let doc = test::mk_doc(~"struct Foo { field: () }"); + assert doc.cratemod().structs()[0].fields[0] == ~"field"; +} + #[cfg(test)] mod test { diff --git a/src/rustdoc/fold.rs b/src/rustdoc/fold.rs index 26ab6cec959..42347b9a34b 100644 --- a/src/rustdoc/fold.rs +++ b/src/rustdoc/fold.rs @@ -11,6 +11,7 @@ export default_seq_fold_trait; export default_seq_fold_impl; export default_seq_fold_type; +export default_seq_fold_struct; export default_par_fold; export default_par_fold_mod; export default_par_fold_nmod; @@ -31,6 +32,8 @@ type FoldTrait = fn~(fold: Fold, doc: doc::TraitDoc) -> doc::TraitDoc; type FoldImpl = fn~(fold: Fold, doc: doc::ImplDoc) -> doc::ImplDoc; type FoldType = fn~(fold: Fold, doc: doc::TyDoc) -> doc::TyDoc; +type FoldStruct = fn~(fold: Fold, + doc: doc::StructDoc) -> doc::StructDoc; type Fold_ = { ctxt: T, @@ -44,7 +47,8 @@ fold_enum: FoldEnum, fold_trait: FoldTrait, fold_impl: FoldImpl, - fold_type: FoldType + fold_type: FoldType, + fold_struct: FoldStruct }; @@ -62,7 +66,8 @@ fn mk_fold( +fold_enum: FoldEnum, +fold_trait: FoldTrait, +fold_impl: FoldImpl, - +fold_type: FoldType + +fold_type: FoldType, + +fold_struct: FoldStruct ) -> Fold { Fold({ ctxt: ctxt, @@ -76,7 +81,8 @@ fn mk_fold( fold_enum: fold_enum, fold_trait: fold_trait, fold_impl: fold_impl, - fold_type: fold_type + fold_type: fold_type, + fold_struct: fold_struct, }) } @@ -93,7 +99,8 @@ fn default_any_fold(ctxt: T) -> Fold { |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d) + |f, d| default_seq_fold_type(f, d), + |f, d| default_seq_fold_struct(f, d) ) } @@ -110,7 +117,8 @@ fn default_seq_fold(ctxt: T) -> Fold { |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d) + |f, d| default_seq_fold_type(f, d), + |f, d| default_seq_fold_struct(f, d) ) } @@ -127,7 +135,8 @@ fn default_par_fold(ctxt: T) -> Fold { |f, d| default_seq_fold_enum(f, d), |f, d| default_seq_fold_trait(f, d), |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d) + |f, d| default_seq_fold_type(f, d), + |f, d| default_seq_fold_struct(f, d) ) } @@ -267,6 +276,9 @@ fn fold_ItemTag(fold: Fold, doc: doc::ItemTag) -> doc::ItemTag { doc::TyTag(TyDoc) => { doc::TyTag(fold.fold_type(fold, TyDoc)) } + doc::StructTag(StructDoc) => { + doc::StructTag(fold.fold_struct(fold, StructDoc)) + } } } @@ -330,6 +342,16 @@ fn default_seq_fold_type( } } +fn default_seq_fold_struct( + fold: Fold, + doc: doc::StructDoc +) -> doc::StructDoc { + { + item: fold.fold_item(fold, doc.item), + .. doc + } +} + #[test] fn default_fold_should_produce_same_doc() { let source = ~"mod a { fn b() { } mod c { fn d() { } } }"; diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs index db79c07e712..c53d7e4c89c 100644 --- a/src/rustdoc/markdown_pass.rs +++ b/src/rustdoc/markdown_pass.rs @@ -210,6 +210,9 @@ fn header_kind(doc: doc::ItemTag) -> ~str { doc::TyTag(_) => { ~"Type" } + doc::StructTag(_) => { + ~"Struct" + } } } @@ -370,7 +373,8 @@ fn write_item_(ctxt: Ctxt, doc: doc::ItemTag, write_header: bool) { doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc), doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc), doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc), - doc::TyTag(TyDoc) => write_type(ctxt, TyDoc) + doc::TyTag(TyDoc) => write_type(ctxt, TyDoc), + doc::StructTag(StructDoc) => write_struct(ctxt, StructDoc), } } @@ -775,6 +779,20 @@ fn should_write_type_signature() { assert str::contains(markdown, ~"\n\n type t = int\n\n"); } +fn write_struct( + ctxt: Ctxt, + doc: doc::StructDoc +) { + write_sig(ctxt, doc.sig); + write_common(ctxt, doc.desc(), doc.sections()); +} + +#[test] +fn should_write_struct_header() { + let markdown = test::render(~"struct S { field: () }"); + assert str::contains(markdown, ~"## Struct `S`\n\n"); +} + #[cfg(test)] mod test { fn render(source: ~str) -> ~str { diff --git a/src/rustdoc/sort_item_type_pass.rs b/src/rustdoc/sort_item_type_pass.rs index ea53a2e3749..70ad14e1efd 100644 --- a/src/rustdoc/sort_item_type_pass.rs +++ b/src/rustdoc/sort_item_type_pass.rs @@ -11,11 +11,12 @@ fn mk_pass() -> Pass { doc::ConstTag(_) => 0, doc::TyTag(_) => 1, doc::EnumTag(_) => 2, - doc::TraitTag(_) => 3, - doc::ImplTag(_) => 4, - doc::FnTag(_) => 5, - doc::ModTag(_) => 6, - doc::NmodTag(_) => 7 + doc::StructTag(_) => 3, + doc::TraitTag(_) => 4, + doc::ImplTag(_) => 5, + doc::FnTag(_) => 6, + doc::ModTag(_) => 7, + doc::NmodTag(_) => 8 } } @@ -35,17 +36,19 @@ fn ifn() { } \ enum ienum { ivar } \ trait itrait { fn a(); } \ impl int { fn a() { } } \ - type itype = int;"; + type itype = int; \ + struct istruct { f: () }"; do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); let doc = mk_pass().f(srv, doc); assert doc.cratemod().items[0].name() == ~"iconst"; assert doc.cratemod().items[1].name() == ~"itype"; assert doc.cratemod().items[2].name() == ~"ienum"; - assert doc.cratemod().items[3].name() == ~"itrait"; - assert doc.cratemod().items[4].name() == ~"__extensions__"; - assert doc.cratemod().items[5].name() == ~"ifn"; - assert doc.cratemod().items[6].name() == ~"imod"; - assert doc.cratemod().items[7].name() == ~"inmod"; + assert doc.cratemod().items[3].name() == ~"istruct"; + assert doc.cratemod().items[4].name() == ~"itrait"; + assert doc.cratemod().items[5].name() == ~"__extensions__"; + assert doc.cratemod().items[6].name() == ~"ifn"; + assert doc.cratemod().items[7].name() == ~"imod"; + assert doc.cratemod().items[8].name() == ~"inmod"; } } diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs index fa6e5c032df..64c99e7abd2 100644 --- a/src/rustdoc/tystr_pass.rs +++ b/src/rustdoc/tystr_pass.rs @@ -27,6 +27,7 @@ fn run( fold_trait: fold_trait, fold_impl: fold_impl, fold_type: fold_type, + fold_struct: fold_struct, .. *fold::default_any_fold(srv) }); fold.fold_doc(fold, doc) @@ -322,6 +323,32 @@ fn should_add_type_signatures() { assert doc.cratemod().types()[0].sig == Some(~"type t = int"); } +fn fold_struct( + fold: fold::Fold, + doc: doc::StructDoc +) -> doc::StructDoc { + let srv = fold.ctxt; + + { + sig: do astsrv::exec(srv) |ctxt| { + match ctxt.ast_map.get(doc.id()) { + ast_map::node_item(item, _) => { + Some(pprust::item_to_str(item, + extract::interner())) + } + _ => fail ~"not an item" + } + }, + .. doc + } +} + +#[test] +fn should_add_struct_defs() { + let doc = test::mk_doc(~"struct S { field: () }"); + assert doc.cratemod().structs()[0].sig.get().contains("struct S {"); +} + #[cfg(test)] mod test { fn mk_doc(source: ~str) -> doc::Doc { -- GitLab