auto merge of #9540 : alexcrichton/rust/more-rustdoc-improvements, r=brson

Commit messages have the details, mostly just knocking out more low-hanging-fruit type issues.
This commit is contained in:
bors 2013-09-27 04:51:13 -07:00
commit 74dfd93bad
8 changed files with 204 additions and 43 deletions

View File

@ -16,6 +16,7 @@ use its = syntax::parse::token::ident_to_str;
use syntax;
use syntax::ast;
use syntax::ast_util;
use syntax::attr;
use syntax::attr::AttributeMethods;
use std;
@ -149,6 +150,8 @@ pub enum ItemEnum {
MethodItem(Method),
StructFieldItem(StructField),
VariantItem(Variant),
ForeignFunctionItem(Function),
ForeignStaticItem(Static),
}
#[deriving(Clone, Encodable, Decodable)]
@ -172,6 +175,7 @@ impl Clean<Item> for doctree::Module {
inner: ModuleItem(Module {
items: std::vec::concat(&[self.structs.clean(),
self.enums.clean(), self.fns.clean(),
std::vec::concat(self.foreigns.clean()),
self.mods.clean(), self.typedefs.clean(),
self.statics.clean(), self.traits.clean(),
self.impls.clean(), self.view_items.clean()])
@ -203,6 +207,25 @@ impl Clean<Attribute> for ast::Attribute {
}
}
// This is a rough approximation that gets us what we want.
impl<'self> attr::AttrMetaMethods for &'self Attribute {
fn name(&self) -> @str {
match **self {
Word(ref n) | List(ref n, _) | NameValue(ref n, _) =>
n.to_managed()
}
}
fn value_str(&self) -> Option<@str> {
match **self {
NameValue(_, ref v) => Some(v.to_managed()),
_ => None,
}
}
fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
fn name_str_pair(&self) -> Option<(@str, @str)> { None }
}
#[deriving(Clone, Encodable, Decodable)]
pub struct TyParam {
name: ~str,
@ -968,6 +991,41 @@ impl Clean<ViewListIdent> for ast::path_list_ident {
}
}
impl Clean<~[Item]> for ast::foreign_mod {
fn clean(&self) -> ~[Item] {
self.items.clean()
}
}
impl Clean<Item> for ast::foreign_item {
fn clean(&self) -> Item {
let inner = match self.node {
ast::foreign_item_fn(ref decl, ref generics) => {
ForeignFunctionItem(Function {
decl: decl.clean(),
generics: generics.clean(),
purity: ast::extern_fn,
})
}
ast::foreign_item_static(ref ty, mutbl) => {
ForeignStaticItem(Static {
type_: ty.clean(),
mutability: if mutbl {Mutable} else {Immutable},
expr: ~"",
})
}
};
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
source: self.span.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: inner,
}
}
}
// Utilities
trait ToSource {

View File

@ -30,6 +30,7 @@ pub struct Module {
traits: ~[Trait],
vis: ast::visibility,
impls: ~[Impl],
foreigns: ~[ast::foreign_mod],
view_items: ~[ast::view_item],
}
@ -50,6 +51,7 @@ impl Module {
traits : ~[],
impls : ~[],
view_items : ~[],
foreigns : ~[],
}
}
}

View File

@ -28,6 +28,7 @@ use extra::json::ToJson;
use extra::sort;
use syntax::ast;
use syntax::attr;
use clean;
use doctree;
@ -521,6 +522,14 @@ impl Context {
}
}
}
clean::StructItem(s) => {
let mut it = s.fields.move_iter();
do self.recurse(name) |this| {
for item in it {
f(this, item);
}
}
}
_ => {}
}
}
@ -532,19 +541,21 @@ impl Context {
fn shortty(item: &clean::Item) -> &'static str {
match item.inner {
clean::ModuleItem(*) => "mod",
clean::StructItem(*) => "struct",
clean::EnumItem(*) => "enum",
clean::FunctionItem(*) => "fn",
clean::TypedefItem(*) => "typedef",
clean::StaticItem(*) => "static",
clean::TraitItem(*) => "trait",
clean::ImplItem(*) => "impl",
clean::ViewItemItem(*) => "viewitem",
clean::TyMethodItem(*) => "tymethod",
clean::MethodItem(*) => "method",
clean::StructFieldItem(*) => "structfield",
clean::VariantItem(*) => "variant",
clean::ModuleItem(*) => "mod",
clean::StructItem(*) => "struct",
clean::EnumItem(*) => "enum",
clean::FunctionItem(*) => "fn",
clean::TypedefItem(*) => "typedef",
clean::StaticItem(*) => "static",
clean::TraitItem(*) => "trait",
clean::ImplItem(*) => "impl",
clean::ViewItemItem(*) => "viewitem",
clean::TyMethodItem(*) => "tymethod",
clean::MethodItem(*) => "method",
clean::StructFieldItem(*) => "structfield",
clean::VariantItem(*) => "variant",
clean::ForeignFunctionItem(*) => "ffi",
clean::ForeignStaticItem(*) => "ffs",
}
}
@ -558,6 +569,18 @@ impl<'self> Item<'self> {
impl<'self> fmt::Default for Item<'self> {
fn fmt(it: &Item<'self>, fmt: &mut fmt::Formatter) {
match attr::find_stability(it.item.attrs.iter()) {
Some(stability) => {
write!(fmt.buf,
"<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
lvl = stability.level.to_str(),
reason = match stability.text {
Some(s) => s, None => @"",
});
}
None => {}
}
// Write the breadcrumb trail header for the top
write!(fmt.buf, "<h1 class='fqn'>");
match it.item.inner {
@ -584,12 +607,15 @@ impl<'self> fmt::Default for Item<'self> {
match it.item.inner {
clean::ModuleItem(ref m) => item_module(fmt.buf, it.cx,
it.item, m.items),
clean::FunctionItem(ref f) => item_function(fmt.buf, it.item, f),
clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) =>
item_function(fmt.buf, it.item, f),
clean::TraitItem(ref t) => item_trait(fmt.buf, it.item, t),
clean::StructItem(ref s) => item_struct(fmt.buf, it.item, s),
clean::EnumItem(ref e) => item_enum(fmt.buf, it.item, e),
clean::TypedefItem(ref t) => item_typedef(fmt.buf, it.item, t),
clean::VariantItem(*) => item_variant(fmt.buf, it.cx, it.item),
clean::StructFieldItem(*) => item_struct_field(fmt.buf, it.cx,
it.item),
_ => {}
}
}
@ -663,6 +689,10 @@ fn item_module(w: &mut io::Writer, cx: &Context,
(_, &clean::EnumItem(*)) => false,
(&clean::StaticItem(*), _) => true,
(_, &clean::StaticItem(*)) => false,
(&clean::ForeignFunctionItem(*), _) => true,
(_, &clean::ForeignFunctionItem(*)) => false,
(&clean::ForeignStaticItem(*), _) => true,
(_, &clean::ForeignStaticItem(*)) => false,
(&clean::TraitItem(*), _) => true,
(_, &clean::TraitItem(*)) => false,
(&clean::FunctionItem(*), _) => true,
@ -690,27 +720,31 @@ fn item_module(w: &mut io::Writer, cx: &Context,
}
curty = myty;
write!(w, "<h2>{}</h2>\n<table>", match myitem.inner {
clean::ModuleItem(*) => "Modules",
clean::StructItem(*) => "Structs",
clean::EnumItem(*) => "Enums",
clean::FunctionItem(*) => "Functions",
clean::TypedefItem(*) => "Type Definitions",
clean::StaticItem(*) => "Statics",
clean::TraitItem(*) => "Traits",
clean::ImplItem(*) => "Implementations",
clean::ViewItemItem(*) => "Reexports",
clean::TyMethodItem(*) => "Type Methods",
clean::MethodItem(*) => "Methods",
clean::StructFieldItem(*) => "Struct Fields",
clean::VariantItem(*) => "Variants",
clean::ModuleItem(*) => "Modules",
clean::StructItem(*) => "Structs",
clean::EnumItem(*) => "Enums",
clean::FunctionItem(*) => "Functions",
clean::TypedefItem(*) => "Type Definitions",
clean::StaticItem(*) => "Statics",
clean::TraitItem(*) => "Traits",
clean::ImplItem(*) => "Implementations",
clean::ViewItemItem(*) => "Reexports",
clean::TyMethodItem(*) => "Type Methods",
clean::MethodItem(*) => "Methods",
clean::StructFieldItem(*) => "Struct Fields",
clean::VariantItem(*) => "Variants",
clean::ForeignFunctionItem(*) => "Foreign Functions",
clean::ForeignStaticItem(*) => "Foreign Statics",
});
}
match myitem.inner {
clean::StaticItem(ref s) => {
clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => {
struct Initializer<'self>(&'self str);
impl<'self> fmt::Default for Initializer<'self> {
fn fmt(s: &Initializer<'self>, f: &mut fmt::Formatter) {
if s.len() == 0 { return; }
write!(f.buf, "<code> = </code>");
let tag = if s.contains("\n") { "pre" } else { "code" };
write!(f.buf, "<{tag}>{}</{tag}>",
s.as_slice(), tag=tag);
@ -719,7 +753,7 @@ fn item_module(w: &mut io::Writer, cx: &Context,
write!(w, "
<tr>
<td><code>{}static {}: {} = </code>{}</td>
<td><code>{}static {}: {}</code>{}</td>
<td class='docblock'>{}&nbsp;</td>
</tr>
",
@ -980,11 +1014,12 @@ fn render_struct(w: &mut io::Writer, it: &clean::Item,
for field in fields.iter() {
match field.inner {
clean::StructFieldItem(ref ty) => {
write!(w, " {}{}: {},\n{}",
write!(w, " {}<a name='field.{name}'>{name}</a>: \
{},\n{}",
VisSpace(field.visibility),
field.name.get_ref().as_slice(),
ty.type_,
tab);
tab,
name = field.name.get_ref().as_slice());
}
_ => unreachable!()
}
@ -1170,3 +1205,12 @@ fn item_variant(w: &mut io::Writer, cx: &Context, it: &clean::Item) {
*cx.current.last(),
it.name.get_ref().as_slice());
}
fn item_struct_field(w: &mut io::Writer, cx: &Context, it: &clean::Item) {
write!(w, "<DOCTYPE html><html><head>\
<meta http-equiv='refresh' content='0; \
url=../struct.{}.html\\#field.{}'>\
</head><body></body></html>",
*cx.current.last(),
it.name.get_ref().as_slice());
}

View File

@ -269,3 +269,18 @@ a {
float: left;
padding: 20px;
}
.stability {
border-left: 5px solid #000;
border-radius: 3px;
padding: 0 3px;
float: right;
background: #fff;
text-transform: lowercase;
}
.stability.Deprecated { border-color: #D60027; color: #880017; }
.stability.Experimental { border-color: #EC5315; color: #a53c0e; }
.stability.Unstable { border-color: #FFD700; color: #b39800; }
.stability.Stable { border-color: #AEC516; color: #7c8b10; }
.stability.Frozen { border-color: #009431; color: #007726; }
.stability.Locked { border-color: #0084B6; color: #00668c; }

View File

@ -10,6 +10,7 @@
use std::num;
use std::uint;
use std::hashmap::HashSet;
use syntax::ast;
@ -50,16 +51,18 @@ pub fn strip_hidden(crate: clean::Crate) -> plugins::PluginResult {
/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
struct Stripper;
impl fold::DocFolder for Stripper {
pub fn strip_private(mut crate: clean::Crate) -> plugins::PluginResult {
// This stripper collects all *retained* nodes.
struct Stripper<'self>(&'self mut HashSet<ast::NodeId>);
impl<'self> fold::DocFolder for Stripper<'self> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match i.inner {
// These items can all get re-exported
clean::TypedefItem(*) | clean::StaticItem(*) |
clean::StructItem(*) | clean::EnumItem(*) |
clean::TraitItem(*) | clean::FunctionItem(*) |
clean::ViewItemItem(*) | clean::MethodItem(*) => {
clean::ViewItemItem(*) | clean::MethodItem(*) |
clean::ForeignFunctionItem(*) | clean::ForeignStaticItem(*) => {
// XXX: re-exported items should get surfaced in the docs as
// well (using the output of resolve analysis)
if i.visibility != Some(ast::public) {
@ -97,6 +100,7 @@ pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
};
let i = if fastreturn {
self.insert(i.id);
return Some(i);
} else {
self.fold_item_recur(i)
@ -108,15 +112,50 @@ pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult {
// emptied modules/impls have no need to exist
clean::ModuleItem(ref m) if m.items.len() == 0 => None,
clean::ImplItem(ref i) if i.methods.len() == 0 => None,
_ => Some(i),
_ => {
self.insert(i.id);
Some(i)
}
}
}
None => None,
}
}
}
let mut stripper = Stripper;
let crate = stripper.fold_crate(crate);
// This stripper discards all private impls of traits
struct ImplStripper<'self>(&'self HashSet<ast::NodeId>);
impl<'self> fold::DocFolder for ImplStripper<'self> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match i.inner {
clean::ImplItem(ref imp) => {
match imp.trait_ {
Some(clean::ResolvedPath{ id, _ }) => {
if !self.contains(&id) {
return None;
}
}
Some(*) | None => {}
}
}
_ => {}
}
self.fold_item_recur(i)
}
}
let mut retained = HashSet::new();
// First, strip all private items
{
let mut stripper = Stripper(&mut retained);
crate = stripper.fold_crate(crate);
}
// Next, strip all private implementations of traits
{
let mut stripper = ImplStripper(&retained);
crate = stripper.fold_crate(crate);
}
(crate, None)
}

View File

@ -174,6 +174,9 @@ impl RustdocVisitor {
};
om.impls.push(i);
},
ast::item_foreign_mod(ref fm) => {
om.foreigns.push(fm.clone());
}
_ => (),
}
}

View File

@ -320,7 +320,7 @@ pub struct Stability {
}
/// The available stability levels.
#[deriving(Eq,Ord,Clone)]
#[deriving(Eq,Ord,Clone,ToStr)]
pub enum StabilityLevel {
Deprecated,
Experimental,

View File

@ -4219,9 +4219,9 @@ impl Parser {
}
// parse a function declaration from a foreign module
fn parse_item_foreign_fn(&self, attrs: ~[Attribute]) -> @foreign_item {
fn parse_item_foreign_fn(&self, vis: ast::visibility,
attrs: ~[Attribute]) -> @foreign_item {
let lo = self.span.lo;
let vis = self.parse_visibility();
// Parse obsolete purity.
let purity = self.parse_fn_purity();
@ -4755,7 +4755,7 @@ impl Parser {
if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) ||
self.is_keyword(keywords::Unsafe)) {
// FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(attrs);
let item = self.parse_item_foreign_fn(visibility, attrs);
return iovi_foreign_item(item);
}
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)