2011-12-20 16:15:49 -06:00
|
|
|
/* rustdoc: rust -> markdown translator
|
2011-12-20 16:19:46 -06:00
|
|
|
* Copyright 2011 Google Inc.
|
2011-12-20 15:52:04 -06:00
|
|
|
*/
|
|
|
|
|
|
|
|
use std;
|
|
|
|
use rustc;
|
|
|
|
|
|
|
|
import option;
|
|
|
|
import option::{some, none};
|
2012-01-13 19:33:16 -06:00
|
|
|
import rustc::driver::diagnostic;
|
2011-12-20 15:52:04 -06:00
|
|
|
import rustc::syntax::ast;
|
|
|
|
import rustc::syntax::codemap;
|
|
|
|
import rustc::syntax::parse::parser;
|
|
|
|
import rustc::syntax::print::pprust;
|
|
|
|
import rustc::syntax::visit;
|
|
|
|
import std::io;
|
2012-01-11 08:15:54 -06:00
|
|
|
import io::writer_util;
|
2011-12-20 15:52:04 -06:00
|
|
|
import std::map;
|
|
|
|
|
|
|
|
type rustdoc = {
|
|
|
|
ps: pprust::ps,
|
|
|
|
w: io::writer
|
|
|
|
};
|
|
|
|
|
2012-01-15 17:05:06 -06:00
|
|
|
type cratedoc = {
|
|
|
|
mods: [moddoc]
|
|
|
|
};
|
|
|
|
|
|
|
|
type moddoc = {
|
|
|
|
fns: [fndoc]
|
|
|
|
};
|
|
|
|
|
2011-12-20 15:52:04 -06:00
|
|
|
type fndoc = {
|
|
|
|
brief: str,
|
|
|
|
desc: option::t<str>,
|
|
|
|
return: option::t<str>,
|
|
|
|
args: map::hashmap<str, str>
|
|
|
|
};
|
|
|
|
|
|
|
|
#[doc(
|
|
|
|
brief = "Documents a single function.",
|
|
|
|
args(rd = "Rustdoc context",
|
|
|
|
ident = "Identifier for this function",
|
|
|
|
doc = "Function docs extracted from attributes",
|
|
|
|
_fn = "AST object representing this function")
|
|
|
|
)]
|
2011-12-22 15:16:02 -06:00
|
|
|
fn doc_fn(rd: rustdoc, ident: str, doc: fndoc, decl: ast::fn_decl) {
|
2011-12-20 15:52:04 -06:00
|
|
|
rd.w.write_line("## Function `" + ident + "`");
|
|
|
|
rd.w.write_line(doc.brief);
|
|
|
|
alt doc.desc {
|
|
|
|
some(_d) {
|
|
|
|
rd.w.write_line("");
|
|
|
|
rd.w.write_line(_d);
|
|
|
|
rd.w.write_line("");
|
|
|
|
}
|
|
|
|
none. { }
|
|
|
|
}
|
2011-12-22 15:16:02 -06:00
|
|
|
for arg: ast::arg in decl.inputs {
|
2011-12-20 15:52:04 -06:00
|
|
|
rd.w.write_str("### Argument `" + arg.ident + "`: ");
|
|
|
|
rd.w.write_line("`" + pprust::ty_to_str(arg.ty) + "`");
|
|
|
|
alt doc.args.find(arg.ident) {
|
|
|
|
some(_d) {
|
|
|
|
rd.w.write_line(_d);
|
|
|
|
}
|
|
|
|
none. { }
|
|
|
|
};
|
|
|
|
}
|
2011-12-22 15:16:02 -06:00
|
|
|
rd.w.write_line("### Returns `" + pprust::ty_to_str(decl.output) + "`");
|
2011-12-20 15:52:04 -06:00
|
|
|
alt doc.return {
|
|
|
|
some(_r) { rd.w.write_line(_r); }
|
|
|
|
none. { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(
|
|
|
|
brief = "Parses function docs from a complex #[doc] attribute.",
|
|
|
|
desc = "Supported attributes:
|
|
|
|
|
|
|
|
* `brief`: Brief description
|
|
|
|
* `desc`: Long description
|
|
|
|
* `return`: Description of return value
|
|
|
|
* `args`: List of argname = argdesc pairs
|
|
|
|
",
|
|
|
|
args(items = "Doc attribute contents"),
|
|
|
|
return = "Parsed function docs."
|
|
|
|
)]
|
|
|
|
fn parse_compound_fndoc(items: [@ast::meta_item]) -> fndoc {
|
|
|
|
let brief = none;
|
|
|
|
let desc = none;
|
|
|
|
let return = none;
|
|
|
|
let argdocs = map::new_str_hash::<str>();
|
|
|
|
let argdocsfound = none;
|
|
|
|
for item: @ast::meta_item in items {
|
|
|
|
alt item.node {
|
|
|
|
ast::meta_name_value("brief", {node: ast::lit_str(value),
|
|
|
|
span: _}) {
|
|
|
|
brief = some(value);
|
|
|
|
}
|
|
|
|
ast::meta_name_value("desc", {node: ast::lit_str(value),
|
|
|
|
span: _}) {
|
|
|
|
desc = some(value);
|
|
|
|
}
|
|
|
|
ast::meta_name_value("return", {node: ast::lit_str(value),
|
|
|
|
span: _}) {
|
|
|
|
return = some(value);
|
|
|
|
}
|
|
|
|
ast::meta_list("args", args) {
|
|
|
|
argdocsfound = some(args);
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
alt argdocsfound {
|
|
|
|
none. { }
|
|
|
|
some(ds) {
|
|
|
|
for d: @ast::meta_item in ds {
|
|
|
|
alt d.node {
|
|
|
|
ast::meta_name_value(key, {node: ast::lit_str(value),
|
|
|
|
span: _}) {
|
|
|
|
argdocs.insert(key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let _brief = alt brief {
|
|
|
|
some(_b) { _b }
|
|
|
|
none. { "_undocumented_" }
|
|
|
|
};
|
|
|
|
|
|
|
|
{ brief: _brief, desc: desc, return: return, args: argdocs }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(
|
|
|
|
brief = "Documents a single crate item.",
|
|
|
|
args(rd = "Rustdoc context",
|
|
|
|
item = "AST item to document")
|
|
|
|
)]
|
|
|
|
fn doc_item(rd: rustdoc, item: @ast::item) {
|
|
|
|
let _fndoc = none;
|
|
|
|
let noargdocs = map::new_str_hash::<str>();
|
|
|
|
for attr: ast::attribute in item.attrs {
|
|
|
|
alt attr.node.value.node {
|
2012-01-15 16:29:53 -06:00
|
|
|
ast::meta_name_value(
|
|
|
|
"doc", {node: ast::lit_str(value), span: _}) {
|
2011-12-20 15:52:04 -06:00
|
|
|
_fndoc = some({ brief: value,
|
|
|
|
desc: none,
|
|
|
|
return: none,
|
|
|
|
args: noargdocs });
|
|
|
|
}
|
|
|
|
ast::meta_list("doc", docs) {
|
|
|
|
_fndoc = some(parse_compound_fndoc(docs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let _fndoc0 = alt _fndoc {
|
|
|
|
some(_d) { _d }
|
2012-01-15 16:29:53 -06:00
|
|
|
none. { { brief: "_undocumented_",
|
|
|
|
desc: none,
|
|
|
|
return: none,
|
|
|
|
args: noargdocs } }
|
2011-12-20 15:52:04 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
alt item.node {
|
|
|
|
ast::item_const(ty, expr) { }
|
2011-12-22 15:16:02 -06:00
|
|
|
ast::item_fn(decl, _, _) {
|
|
|
|
doc_fn(rd, item.ident, _fndoc0, decl);
|
2011-12-20 15:52:04 -06:00
|
|
|
}
|
|
|
|
ast::item_mod(_mod) { }
|
|
|
|
ast::item_ty(ty, typarams) { }
|
|
|
|
ast::item_tag(variant, typarams) { }
|
2011-12-22 15:16:02 -06:00
|
|
|
ast::item_res(_, _, _, _, _) { }
|
2011-12-20 15:52:04 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(
|
|
|
|
brief = "Generate a crate document header.",
|
|
|
|
args(rd = "Rustdoc context",
|
|
|
|
name = "Crate name")
|
|
|
|
)]
|
|
|
|
fn doc_header(rd: rustdoc, name: str) {
|
|
|
|
rd.w.write_line("# Crate " + name);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(
|
|
|
|
brief = "Main function.",
|
|
|
|
desc = "Command-line arguments:
|
|
|
|
|
|
|
|
* argv[1]: crate file name",
|
|
|
|
args(argv = "Command-line arguments.")
|
|
|
|
)]
|
|
|
|
fn main(argv: [str]) {
|
2011-12-30 17:26:49 -06:00
|
|
|
|
|
|
|
if vec::len(argv) != 2u {
|
2012-01-15 16:16:55 -06:00
|
|
|
io::println(#fmt("usage: %s <input>", argv[0]));
|
2011-12-30 17:26:49 -06:00
|
|
|
ret;
|
|
|
|
}
|
|
|
|
|
2012-01-15 16:16:55 -06:00
|
|
|
let crate = parse::from_file(argv[1]);
|
|
|
|
|
|
|
|
let w = io::stdout();
|
2011-12-20 15:52:04 -06:00
|
|
|
let rd = { ps: pprust::rust_printer(w), w: w };
|
|
|
|
doc_header(rd, argv[1]);
|
2012-01-15 16:16:55 -06:00
|
|
|
|
2011-12-20 15:52:04 -06:00
|
|
|
let v = visit::mk_simple_visitor(@{
|
|
|
|
visit_item: bind doc_item(rd, _)
|
|
|
|
with *visit::default_simple_visitor()});
|
2012-01-15 16:16:55 -06:00
|
|
|
visit::visit_crate(*crate, (), v);
|
2011-12-20 15:52:04 -06:00
|
|
|
}
|