rustdoc: Simplify attribute parsing
This commit is contained in:
parent
effe4559d2
commit
f9755c666d
@ -9,23 +9,14 @@ import rustc::syntax::ast;
|
||||
import rustc::front::attr;
|
||||
import core::tuple;
|
||||
|
||||
export crate_attrs, basic_attrs, variant_attrs;
|
||||
export parse_crate, parse_basic, parse_variant;
|
||||
export crate_attrs;
|
||||
export parse_crate, parse_desc;
|
||||
export parse_hidden;
|
||||
|
||||
type crate_attrs = {
|
||||
name: option<str>
|
||||
};
|
||||
|
||||
type basic_attrs = {
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
};
|
||||
|
||||
type variant_attrs = {
|
||||
desc: option<str>
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
@ -102,170 +93,44 @@ fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
|
||||
assert attrs.name == none;
|
||||
}
|
||||
|
||||
fn parse_basic(
|
||||
attrs: [ast::attribute]
|
||||
) -> {
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
} {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|desc|
|
||||
{
|
||||
brief: none,
|
||||
desc: desc
|
||||
}
|
||||
},
|
||||
{|_items, brief, desc|
|
||||
{
|
||||
brief: brief,
|
||||
desc: desc
|
||||
}
|
||||
}
|
||||
)
|
||||
fn parse_desc(attrs: [ast::attribute]) -> option<str> {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
attr::get_meta_item_value_str(meta)
|
||||
}
|
||||
none { none }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_handle_undocumented_mods() {
|
||||
fn parse_desc_should_handle_undocumented_mods() {
|
||||
let source = "";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.brief == none;
|
||||
assert attrs.desc == none;
|
||||
let attrs = parse_desc(attrs);
|
||||
assert attrs == none;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_simple_doc_attributes() {
|
||||
fn parse_desc_should_parse_simple_doc_attributes() {
|
||||
let source = "#[doc = \"basic\"]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.desc == some("basic");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_the_brief_description() {
|
||||
let source = "#[doc(brief = \"short\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.brief == some("short");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_basic_should_parse_the_long_description() {
|
||||
let source = "#[doc(desc = \"description\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_basic(attrs);
|
||||
assert attrs.desc == some("description");
|
||||
}
|
||||
|
||||
fn parse_short_doc_or<T>(
|
||||
attrs: [ast::attribute],
|
||||
handle_short: fn&(
|
||||
short_desc: option<str>
|
||||
) -> T,
|
||||
parse_long: fn&(
|
||||
doc_items: [@ast::meta_item],
|
||||
brief: option<str>,
|
||||
desc: option<str>
|
||||
) -> T
|
||||
) -> T {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_value_str(meta) {
|
||||
some(desc) { handle_short(some(desc)) }
|
||||
none {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(list) {
|
||||
let brief = attr::meta_item_value_from_list(list, "brief");
|
||||
let desc = attr::meta_item_value_from_list(list, "desc");
|
||||
parse_long(list, brief, desc)
|
||||
}
|
||||
none {
|
||||
handle_short(none)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
none {
|
||||
handle_short(none)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_long_doc<T>(
|
||||
attrs: [ast::attribute],
|
||||
parse_long: fn&(doc_items: [@ast::meta_item]) -> T
|
||||
) -> T {
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(list) {
|
||||
parse_long(list)
|
||||
}
|
||||
none {
|
||||
parse_long([])
|
||||
}
|
||||
}
|
||||
}
|
||||
none { parse_long([]) }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_variant(attrs: [ast::attribute]) -> variant_attrs {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|desc|
|
||||
{
|
||||
desc: desc
|
||||
}
|
||||
},
|
||||
{|_items, brief, desc|
|
||||
if option::is_some(brief) && option::is_some(desc) {
|
||||
// FIXME: Warn about dropping brief description
|
||||
}
|
||||
|
||||
{
|
||||
// Prefer desc over brief
|
||||
desc: option::maybe(brief, desc, {|s| some(s) })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_short_doc() {
|
||||
let source = "#[doc = \"a\"]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_brief_doc() {
|
||||
let source = "#[doc(brief = \"a\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_parse_variant_long_doc() {
|
||||
let source = "#[doc(desc = \"a\")]";
|
||||
let attrs = test::parse_attributes(source);
|
||||
let attrs = parse_variant(attrs);
|
||||
assert attrs.desc == some("a");
|
||||
let attrs = parse_desc(attrs);
|
||||
assert attrs == some("basic");
|
||||
}
|
||||
|
||||
fn parse_hidden(attrs: [ast::attribute]) -> bool {
|
||||
parse_short_doc_or(
|
||||
attrs,
|
||||
{|_desc| false },
|
||||
{|metas, _brief, _desc|
|
||||
alt doc_meta(attrs) {
|
||||
some(meta) {
|
||||
alt attr::get_meta_item_list(meta) {
|
||||
some(metas) {
|
||||
let hiddens = attr::find_meta_items_by_name(metas, "hidden");
|
||||
vec::is_not_empty(hiddens)
|
||||
}
|
||||
none { false }
|
||||
}
|
||||
)
|
||||
}
|
||||
none { false }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -72,18 +72,17 @@ fn fold_item(
|
||||
let srv = fold.ctxt;
|
||||
let doc = fold::default_seq_fold_item(fold, doc);
|
||||
|
||||
let attrs = if doc.id == ast::crate_node_id {
|
||||
let desc = if doc.id == ast::crate_node_id {
|
||||
// This is the top-level mod, use the crate attributes
|
||||
astsrv::exec(srv) {|ctxt|
|
||||
attr_parser::parse_basic(ctxt.ast.node.attrs)
|
||||
attr_parser::parse_desc(ctxt.ast.node.attrs)
|
||||
}
|
||||
} else {
|
||||
parse_item_attrs(srv, doc.id, attr_parser::parse_basic)
|
||||
parse_item_attrs(srv, doc.id, attr_parser::parse_desc)
|
||||
};
|
||||
|
||||
{
|
||||
brief: attrs.brief,
|
||||
desc: attrs.desc
|
||||
desc: desc
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -134,14 +133,6 @@ fn should_extract_fn_attributes() {
|
||||
assert doc.cratemod().fns()[0].desc() == some("test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_const_docs() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"foo\", desc = \"bar\")]\
|
||||
const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].brief() == some("foo");
|
||||
assert doc.cratemod().consts()[0].desc() == some("bar");
|
||||
}
|
||||
|
||||
fn fold_enum(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::enumdoc
|
||||
@ -153,7 +144,7 @@ fn fold_enum(
|
||||
|
||||
{
|
||||
variants: par::anymap(doc.variants) {|variant|
|
||||
let attrs = astsrv::exec(srv) {|ctxt|
|
||||
let desc = astsrv::exec(srv) {|ctxt|
|
||||
alt check ctxt.ast_map.get(doc_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_enum(ast_variants, _), _
|
||||
@ -163,13 +154,13 @@ fn fold_enum(
|
||||
v.node.name == variant.name
|
||||
});
|
||||
|
||||
attr_parser::parse_variant(ast_variant.node.attrs)
|
||||
attr_parser::parse_desc(ast_variant.node.attrs)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
desc: attrs.desc
|
||||
desc: desc
|
||||
with variant
|
||||
}
|
||||
}
|
||||
@ -179,9 +170,8 @@ fn fold_enum(
|
||||
|
||||
#[test]
|
||||
fn should_extract_enum_docs() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"a\", desc = \"b\")]\
|
||||
let doc = test::mk_doc("#[doc = \"b\"]\
|
||||
enum a { v }");
|
||||
assert doc.cratemod().enums()[0].brief() == some("a");
|
||||
assert doc.cratemod().enums()[0].desc() == some("b");
|
||||
}
|
||||
|
||||
@ -211,20 +201,20 @@ fn merge_method_attrs(
|
||||
) -> [doc::methoddoc] {
|
||||
|
||||
// Create an assoc list from method name to attributes
|
||||
let attrs: [(str, attr_parser::basic_attrs)] = astsrv::exec(srv) {|ctxt|
|
||||
let attrs: [(str, option<str>)] = astsrv::exec(srv) {|ctxt|
|
||||
alt ctxt.ast_map.get(item_id) {
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_iface(_, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods) {|method|
|
||||
(method.ident, attr_parser::parse_basic(method.attrs))
|
||||
(method.ident, attr_parser::parse_desc(method.attrs))
|
||||
}
|
||||
}
|
||||
ast_map::node_item(@{
|
||||
node: ast::item_impl(_, _, _, methods), _
|
||||
}, _) {
|
||||
par::seqmap(methods) {|method|
|
||||
(method.ident, attr_parser::parse_basic(method.attrs))
|
||||
(method.ident, attr_parser::parse_desc(method.attrs))
|
||||
}
|
||||
}
|
||||
_ { fail "unexpected item" }
|
||||
@ -233,11 +223,10 @@ fn merge_method_attrs(
|
||||
|
||||
vec::map2(docs, attrs) {|doc, attrs|
|
||||
assert doc.name == tuple::first(attrs);
|
||||
let basic_attrs = tuple::second(attrs);
|
||||
let desc = tuple::second(attrs);
|
||||
|
||||
{
|
||||
brief: basic_attrs.brief,
|
||||
desc: basic_attrs.desc
|
||||
desc: desc
|
||||
with doc
|
||||
}
|
||||
}
|
||||
@ -290,15 +279,6 @@ fn should_extract_impl_method_docs() {
|
||||
assert doc.cratemod().impls()[0].methods[0].desc == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_extract_type_docs() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \"brief\", desc = \"desc\")]\
|
||||
type t = int;");
|
||||
assert doc.cratemod().types()[0].brief() == some("brief");
|
||||
assert doc.cratemod().types()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
|
@ -145,7 +145,7 @@ fn should_index_mod_contents_multi_page() {
|
||||
fn should_add_brief_desc_to_index() {
|
||||
let doc = test::mk_doc(
|
||||
config::doc_per_mod,
|
||||
"#[doc(brief = \"test\")] mod a { }"
|
||||
"#[doc = \"test\"] mod a { }"
|
||||
);
|
||||
assert option::get(doc.cratemod().index).entries[0].brief == some("test");
|
||||
}
|
||||
@ -160,6 +160,7 @@ mod test {
|
||||
};
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
let doc = path_pass::mk_pass().f(srv, doc);
|
||||
run(srv, doc, config)
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ fn should_write_index() {
|
||||
|
||||
#[test]
|
||||
fn should_write_index_brief() {
|
||||
let markdown = test::render("#[doc(brief = \"test\")] mod a { }");
|
||||
let markdown = test::render("#[doc = \"test\"] mod a { }");
|
||||
assert str::contains(markdown, "(#module-a) - test\n");
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ fn should_write_iface_header() {
|
||||
#[test]
|
||||
fn should_write_iface_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] iface i { fn a(); }");
|
||||
"#[doc = \"desc\"] iface i { fn a(); }");
|
||||
assert str::contains(markdown, "desc");
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ fn should_write_impl_header_with_iface() {
|
||||
#[test]
|
||||
fn should_write_impl_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] impl i for int { fn a() { } }");
|
||||
"#[doc = \"desc\"] impl i for int { fn a() { } }");
|
||||
assert str::contains(markdown, "desc");
|
||||
}
|
||||
|
||||
@ -692,7 +692,7 @@ fn should_write_type_header() {
|
||||
#[test]
|
||||
fn should_write_type_desc() {
|
||||
let markdown = test::render(
|
||||
"#[doc(desc = \"desc\")] type t = int;");
|
||||
"#[doc = \"desc\"] type t = int;");
|
||||
assert str::contains(markdown, "\n\ndesc\n\n");
|
||||
}
|
||||
|
||||
@ -727,6 +727,8 @@ mod test {
|
||||
#debug("doc (path): %?", doc);
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (attr): %?", doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (desc_to_brief): %?", doc);
|
||||
let doc = unindent_pass::mk_pass().f(srv, doc);
|
||||
#debug("doc (unindent): %?", doc);
|
||||
let doc = sectionalize_pass::mk_pass().f(srv, doc);
|
||||
|
@ -98,13 +98,13 @@ fn fold_impl(fold: fold::fold<op>, doc: doc::impldoc) -> doc::impldoc {
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_enum_brief() {
|
||||
let doc = test::mk_doc("#[doc(brief = \" a \")] enum a { b }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] enum a { b }");
|
||||
assert doc.cratemod().enums()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_enum_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \" a \")] enum a { b }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] enum a { b }");
|
||||
assert doc.cratemod().enums()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
@ -116,83 +116,83 @@ fn should_execute_op_on_variant_desc() {
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_resource_brief() {
|
||||
let doc = test::mk_doc("#[doc(brief = \" a \")] resource r(a: bool) { }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_resource_desc() {
|
||||
let doc = test::mk_doc("#[doc(desc = \" a \")] resource r(a: bool) { }");
|
||||
let doc = test::mk_doc("#[doc = \" a \"] resource r(a: bool) { }");
|
||||
assert doc.cratemod().resources()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] iface i { fn a(); }");
|
||||
"#[doc = \" a \"] iface i { fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] iface i { fn a(); }");
|
||||
"#[doc = \" a \"] iface i { fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(brief = \" a \")] fn a(); }");
|
||||
"iface i { #[doc = \" a \"] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].brief == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_iface_method_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"iface i { #[doc(desc = \" a \")] fn a(); }");
|
||||
"iface i { #[doc = \" a \"] fn a(); }");
|
||||
assert doc.cratemod().ifaces()[0].methods[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] impl i for int { fn a() { } }");
|
||||
"#[doc = \" a \"] impl i for int { fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] impl i for int { fn a() { } }");
|
||||
"#[doc = \" a \"] impl i for int { fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(brief = \" a \")] fn a() { } }");
|
||||
"impl i for int { #[doc = \" a \"] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].brief == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_impl_method_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"impl i for int { #[doc(desc = \" a \")] fn a() { } }");
|
||||
"impl i for int { #[doc = \" a \"] fn a() { } }");
|
||||
assert doc.cratemod().impls()[0].methods[0].desc == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_type_brief() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(brief = \" a \")] type t = int;");
|
||||
"#[doc = \" a \"] type t = int;");
|
||||
assert doc.cratemod().types()[0].brief() == some("a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_execute_op_on_type_desc() {
|
||||
let doc = test::mk_doc(
|
||||
"#[doc(desc = \" a \")] type t = int;");
|
||||
"#[doc = \" a \"] type t = int;");
|
||||
assert doc.cratemod().types()[0].desc() == some("a");
|
||||
}
|
||||
|
||||
@ -268,6 +268,7 @@ mod test {
|
||||
astsrv::from_str(source) {|srv|
|
||||
let doc = extract::from_srv(srv, "");
|
||||
let doc = attr_pass::mk_pass().f(srv, doc);
|
||||
let doc = desc_to_brief_pass::mk_pass().f(srv, doc);
|
||||
let doc = sectionalize_pass::mk_pass().f(srv, doc);
|
||||
mk_pass("", {|s| str::trim(s)}).f(srv, doc)
|
||||
}
|
||||
|
@ -14,32 +14,12 @@ fn mk_pass() -> pass {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_mod() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
fn should_trim_text() {
|
||||
let doc = test::mk_doc("#[doc = \" desc \"] \
|
||||
mod m { }");
|
||||
assert doc.cratemod().mods()[0].brief() == some("brief");
|
||||
assert doc.cratemod().mods()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_const() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
const a: bool = true;");
|
||||
assert doc.cratemod().consts()[0].brief() == some("brief");
|
||||
assert doc.cratemod().consts()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_trim_fn() {
|
||||
let doc = test::mk_doc("#[doc(brief = \"\nbrief\n\", \
|
||||
desc = \"\ndesc\n\")] \
|
||||
fn a() { }");
|
||||
assert doc.cratemod().fns()[0].brief() == some("brief");
|
||||
assert doc.cratemod().fns()[0].desc() == some("desc");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
fn mk_doc(source: str) -> doc::doc {
|
||||
|
Loading…
x
Reference in New Issue
Block a user