Skip to content

Commit

Permalink
auto merge of #19174 : tomjakubowski/rust/rustdoc-assoc-types, r=alex…
Browse files Browse the repository at this point in the history
…crichton

Render associated types on traits and impls, and qualified paths in types.

r? @alexcrichton
  • Loading branch information
bors committed Nov 25, 2014
2 parents 2264049 + de94f0a commit 48ca6d1
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 40 deletions.
40 changes: 37 additions & 3 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -336,7 +336,7 @@ pub enum ItemEnum {
ForeignStaticItem(Static),
MacroItem(Macro),
PrimitiveItem(PrimitiveType),
AssociatedTypeItem,
AssociatedTypeItem(TyParam),
}

#[deriving(Clone, Encodable, Decodable)]
Expand Down Expand Up @@ -982,6 +982,8 @@ impl Clean<Type> for ast::PolyTraitRef {
}
}

/// An item belonging to a trait, whether a method or associated. Could be named
/// TraitItem except that's already taken by an exported enum variant.
#[deriving(Clone, Encodable, Decodable)]
pub enum TraitMethod {
RequiredMethod(Item),
Expand All @@ -1002,6 +1004,12 @@ impl TraitMethod {
_ => false,
}
}
pub fn is_type(&self) -> bool {
match self {
&TypeTraitItem(..) => true,
_ => false,
}
}
pub fn item<'a>(&'a self) -> &'a Item {
match *self {
RequiredMethod(ref item) => item,
Expand Down Expand Up @@ -1127,6 +1135,11 @@ pub enum Type {
mutability: Mutability,
type_: Box<Type>,
},
QPath {
name: String,
self_type: Box<Type>,
trait_: Box<Type>
},
// region, raw, other boxes, mutable
}

Expand Down Expand Up @@ -1252,6 +1265,7 @@ impl Clean<Type> for ast::Ty {
TyProc(ref c) => Proc(box c.clean(cx)),
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyParen(ref ty) => ty.clean(cx),
TyQPath(ref qp) => qp.clean(cx),
ref x => panic!("Unimplemented type {}", x),
}
}
Expand Down Expand Up @@ -1354,6 +1368,16 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
}
}

impl Clean<Type> for ast::QPath {
fn clean(&self, cx: &DocContext) -> Type {
Type::QPath {
name: self.item_name.clean(cx),
self_type: box self.self_type.clean(cx),
trait_: box self.trait_ref.clean(cx)
}
}
}

#[deriving(Clone, Encodable, Decodable)]
pub enum StructField {
HiddenStructField, // inserted later by strip passes
Expand Down Expand Up @@ -2211,7 +2235,7 @@ impl Clean<Item> for ast::AssociatedType {
source: self.ty_param.span.clean(cx),
name: Some(self.ty_param.ident.clean(cx)),
attrs: self.attrs.clean(cx),
inner: AssociatedTypeItem,
inner: AssociatedTypeItem(self.ty_param.clean(cx)),
visibility: None,
def_id: ast_util::local_def(self.ty_param.id),
stability: None,
Expand All @@ -2225,7 +2249,17 @@ impl Clean<Item> for ty::AssociatedType {
source: DUMMY_SP.clean(cx),
name: Some(self.name.clean(cx)),
attrs: Vec::new(),
inner: AssociatedTypeItem,
// FIXME(#18048): this is wrong, but cross-crate associated types are broken
// anyway, for the time being.
inner: AssociatedTypeItem(TyParam {
name: self.name.clean(cx),
did: ast::DefId {
krate: 0,
node: ast::DUMMY_NODE_ID
},
bounds: vec![],
default: None
}),
visibility: None,
def_id: self.def_id,
stability: None,
Expand Down
6 changes: 4 additions & 2 deletions src/librustdoc/html/format.rs
Expand Up @@ -46,9 +46,8 @@ pub struct Stability<'a>(pub &'a Option<clean::Stability>);
pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
/// Wrapper struct for emitting a where clause from Generics.
pub struct WhereClause<'a>(pub &'a clean::Generics);

/// Wrapper struct for emitting type parameter bounds.
struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);

impl VisSpace {
pub fn get(&self) -> Option<ast::Visibility> {
Expand Down Expand Up @@ -486,6 +485,9 @@ impl fmt::Show for clean::Type {
}
}
}
clean::QPath { ref name, ref self_type, ref trait_ } => {
write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
}
clean::Unique(..) => {
panic!("should have been cleaned")
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/item_type.rs
Expand Up @@ -95,7 +95,7 @@ pub fn shortty(item: &clean::Item) -> ItemType {
clean::ForeignStaticItem(..) => ForeignStatic,
clean::MacroItem(..) => Macro,
clean::PrimitiveItem(..) => Primitive,
clean::AssociatedTypeItem => AssociatedType,
clean::AssociatedTypeItem(..) => AssociatedType,
}
}

92 changes: 65 additions & 27 deletions src/librustdoc/html/render.rs
Expand Up @@ -59,7 +59,7 @@ use clean;
use doctree;
use fold::DocFolder;
use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
use html::format::{ConciseStability, WhereClause};
use html::format::{ConciseStability, TyParamBounds, WhereClause};
use html::highlight;
use html::item_type::{ItemType, shortty};
use html::item_type;
Expand Down Expand Up @@ -1685,27 +1685,23 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t.generics,
bounds,
WhereClause(&t.generics)));
let required = t.items.iter()
.filter(|m| {
match **m {
clean::RequiredMethod(_) => true,
_ => false,
}
})
.collect::<Vec<&clean::TraitMethod>>();
let provided = t.items.iter()
.filter(|m| {
match **m {
clean::ProvidedMethod(_) => true,
_ => false,
}
})
.collect::<Vec<&clean::TraitMethod>>();

let types = t.items.iter().filter(|m| m.is_type()).collect::<Vec<_>>();
let required = t.items.iter().filter(|m| m.is_req()).collect::<Vec<_>>();
let provided = t.items.iter().filter(|m| m.is_def()).collect::<Vec<_>>();

if t.items.len() == 0 {
try!(write!(w, "{{ }}"));
} else {
try!(write!(w, "{{\n"));
for t in types.iter() {
try!(write!(w, " "));
try!(render_method(w, t.item()));
try!(write!(w, ";\n"));
}
if types.len() > 0 && required.len() > 0 {
try!(w.write("\n".as_bytes()));
}
for m in required.iter() {
try!(write!(w, " "));
try!(render_method(w, m.item()));
Expand Down Expand Up @@ -1738,6 +1734,17 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
Ok(())
}

if types.len() > 0 {
try!(write!(w, "
<h2 id='associated-types'>Associated Types</h2>
<div class='methods'>
"));
for t in types.iter() {
try!(trait_item(w, *t));
}
try!(write!(w, "</div>"));
}

// Output the documentation for each function individually
if required.len() > 0 {
try!(write!(w, "
Expand Down Expand Up @@ -1792,7 +1799,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
}

fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
fn fun(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
fn method(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
g: &clean::Generics, selfty: &clean::SelfTy,
d: &clean::FnDecl) -> fmt::Result {
write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
Expand All @@ -1807,14 +1814,28 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
decl = Method(selfty, d),
where_clause = WhereClause(g))
}
fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
typ: &clean::TyParam) -> fmt::Result {
try!(write!(w, "type {}", it.name.as_ref().unwrap()));
if typ.bounds.len() > 0 {
try!(write!(w, ": {}", TyParamBounds(&*typ.bounds)))
}
if let Some(ref default) = typ.default {
try!(write!(w, " = {}", default));
}
Ok(())
}
match meth.inner {
clean::TyMethodItem(ref m) => {
fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
}
clean::MethodItem(ref m) => {
fun(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
}
_ => unreachable!()
clean::AssociatedTypeItem(ref typ) => {
assoc_type(w, meth, typ)
}
_ => panic!("render_method called on non-method")
}
}

Expand Down Expand Up @@ -2071,11 +2092,26 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {

fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
-> fmt::Result {
try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
*item.name.as_ref().unwrap(),
ConciseStability(&item.stability)));
try!(render_method(w, item));
try!(write!(w, "</code></h4>\n"));
match item.inner {
clean::MethodItem(..) | clean::TyMethodItem(..) => {
try!(write!(w, "<h4 id='method.{}' class='{}'>{}<code>",
*item.name.as_ref().unwrap(),
shortty(item),
ConciseStability(&item.stability)));
try!(render_method(w, item));
try!(write!(w, "</code></h4>\n"));
}
clean::TypedefItem(ref tydef) => {
let name = item.name.as_ref().unwrap();
try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>",
*name,
shortty(item),
ConciseStability(&item.stability)));
try!(write!(w, "type {} = {}", name, tydef.type_));
try!(write!(w, "</code></h4>\n"));
}
_ => panic!("can't make docs for trait item with name {}", item.name)
}
match item.doc_value() {
Some(s) if dox => {
try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
Expand All @@ -2085,7 +2121,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
}
}

try!(write!(w, "<div class='impl-methods'>"));
try!(write!(w, "<div class='impl-items'>"));
for trait_item in i.impl_.items.iter() {
try!(doctraititem(w, trait_item, true));
}
Expand All @@ -2107,6 +2143,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {

// If we've implemented a trait, then also emit documentation for all
// default methods which weren't overridden in the implementation block.
// FIXME: this also needs to be done for associated types, whenever defaults
// for them work.
match i.impl_.trait_ {
Some(clean::ResolvedPath { did, .. }) => {
try!({
Expand Down
13 changes: 7 additions & 6 deletions src/librustdoc/html/static/main.css
Expand Up @@ -84,7 +84,7 @@ h2 {
h3 {
font-size: 1.3em;
}
h1, h2, h3:not(.impl):not(.method), h4:not(.method) {
h1, h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
color: black;
font-weight: 500;
margin: 20px 0 15px 0;
Expand All @@ -94,15 +94,15 @@ h1.fqn {
border-bottom: 1px dashed #D5D5D5;
margin-top: 0;
}
h2, h3:not(.impl):not(.method), h4:not(.method) {
h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
border-bottom: 1px solid #DDDDDD;
}
h3.impl, h3.method, h4.method {
h3.impl, h3.method, h4.method, h3.type, h4.type {
font-weight: 600;
margin-top: 10px;
margin-bottom: 10px;
}
h3.impl, h3.method {
h3.impl, h3.method, h3.type {
margin-top: 15px;
}
h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle {
Expand Down Expand Up @@ -235,6 +235,7 @@ nav.sub {
.content .highlighted.fn { background-color: #c6afb3; }
.content .highlighted.method { background-color: #c6afb3; }
.content .highlighted.tymethod { background-color: #c6afb3; }
.content .highlighted.type { background-color: #c6afb3; }
.content .highlighted.ffi { background-color: #c6afb3; }

.docblock.short.nowrap {
Expand Down Expand Up @@ -307,7 +308,7 @@ nav.sub {
}
.content .methods .docblock { margin-left: 40px; }

.content .impl-methods .docblock { margin-left: 40px; }
.content .impl-items .docblock { margin-left: 40px; }

nav {
border-bottom: 1px solid #e0e0e0;
Expand Down Expand Up @@ -442,7 +443,7 @@ h1 .stability {
padding: 4px 10px;
}

.impl-methods .stability, .methods .stability {
.impl-items .stability, .methods .stability {
margin-right: 20px;
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/lib.rs
Expand Up @@ -16,7 +16,7 @@
#![crate_type = "rlib"]

#![allow(unknown_features)]
#![feature(globs, macro_rules, phase, slicing_syntax, tuple_indexing)]
#![feature(globs, if_let, macro_rules, phase, slicing_syntax, tuple_indexing)]

extern crate arena;
extern crate getopts;
Expand Down

0 comments on commit 48ca6d1

Please sign in to comment.