rustdoc: Render associated types on traits and impls
This commit is contained in:
parent
bad1062caa
commit
dd4c7c00d8
@ -336,7 +336,7 @@ pub enum ItemEnum {
|
|||||||
ForeignStaticItem(Static),
|
ForeignStaticItem(Static),
|
||||||
MacroItem(Macro),
|
MacroItem(Macro),
|
||||||
PrimitiveItem(PrimitiveType),
|
PrimitiveItem(PrimitiveType),
|
||||||
AssociatedTypeItem,
|
AssociatedTypeItem(TyParam),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable)]
|
||||||
@ -982,6 +982,8 @@ fn clean(&self, cx: &DocContext) -> Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)]
|
#[deriving(Clone, Encodable, Decodable)]
|
||||||
pub enum TraitMethod {
|
pub enum TraitMethod {
|
||||||
RequiredMethod(Item),
|
RequiredMethod(Item),
|
||||||
@ -1002,6 +1004,12 @@ pub fn is_def(&self) -> bool {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn is_type(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&TypeTraitItem(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn item<'a>(&'a self) -> &'a Item {
|
pub fn item<'a>(&'a self) -> &'a Item {
|
||||||
match *self {
|
match *self {
|
||||||
RequiredMethod(ref item) => item,
|
RequiredMethod(ref item) => item,
|
||||||
@ -2211,7 +2219,7 @@ fn clean(&self, cx: &DocContext) -> Item {
|
|||||||
source: self.ty_param.span.clean(cx),
|
source: self.ty_param.span.clean(cx),
|
||||||
name: Some(self.ty_param.ident.clean(cx)),
|
name: Some(self.ty_param.ident.clean(cx)),
|
||||||
attrs: self.attrs.clean(cx),
|
attrs: self.attrs.clean(cx),
|
||||||
inner: AssociatedTypeItem,
|
inner: AssociatedTypeItem(self.ty_param.clean(cx)),
|
||||||
visibility: None,
|
visibility: None,
|
||||||
def_id: ast_util::local_def(self.ty_param.id),
|
def_id: ast_util::local_def(self.ty_param.id),
|
||||||
stability: None,
|
stability: None,
|
||||||
@ -2225,7 +2233,17 @@ fn clean(&self, cx: &DocContext) -> Item {
|
|||||||
source: DUMMY_SP.clean(cx),
|
source: DUMMY_SP.clean(cx),
|
||||||
name: Some(self.name.clean(cx)),
|
name: Some(self.name.clean(cx)),
|
||||||
attrs: Vec::new(),
|
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,
|
visibility: None,
|
||||||
def_id: self.def_id,
|
def_id: self.def_id,
|
||||||
stability: None,
|
stability: None,
|
||||||
|
@ -46,9 +46,8 @@
|
|||||||
pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
|
pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
|
||||||
/// Wrapper struct for emitting a where clause from Generics.
|
/// Wrapper struct for emitting a where clause from Generics.
|
||||||
pub struct WhereClause<'a>(pub &'a clean::Generics);
|
pub struct WhereClause<'a>(pub &'a clean::Generics);
|
||||||
|
|
||||||
/// Wrapper struct for emitting type parameter bounds.
|
/// Wrapper struct for emitting type parameter bounds.
|
||||||
struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
|
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
|
||||||
|
|
||||||
impl VisSpace {
|
impl VisSpace {
|
||||||
pub fn get(&self) -> Option<ast::Visibility> {
|
pub fn get(&self) -> Option<ast::Visibility> {
|
||||||
|
@ -95,7 +95,7 @@ pub fn shortty(item: &clean::Item) -> ItemType {
|
|||||||
clean::ForeignStaticItem(..) => ForeignStatic,
|
clean::ForeignStaticItem(..) => ForeignStatic,
|
||||||
clean::MacroItem(..) => Macro,
|
clean::MacroItem(..) => Macro,
|
||||||
clean::PrimitiveItem(..) => Primitive,
|
clean::PrimitiveItem(..) => Primitive,
|
||||||
clean::AssociatedTypeItem => AssociatedType,
|
clean::AssociatedTypeItem(..) => AssociatedType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
use doctree;
|
use doctree;
|
||||||
use fold::DocFolder;
|
use fold::DocFolder;
|
||||||
use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
|
use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
|
||||||
use html::format::{ConciseStability, WhereClause};
|
use html::format::{ConciseStability, TyParamBounds, WhereClause};
|
||||||
use html::highlight;
|
use html::highlight;
|
||||||
use html::item_type::{ItemType, shortty};
|
use html::item_type::{ItemType, shortty};
|
||||||
use html::item_type;
|
use html::item_type;
|
||||||
@ -1685,27 +1685,23 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||||||
t.generics,
|
t.generics,
|
||||||
bounds,
|
bounds,
|
||||||
WhereClause(&t.generics)));
|
WhereClause(&t.generics)));
|
||||||
let required = t.items.iter()
|
|
||||||
.filter(|m| {
|
let types = t.items.iter().filter(|m| m.is_type()).collect::<Vec<_>>();
|
||||||
match **m {
|
let required = t.items.iter().filter(|m| m.is_req()).collect::<Vec<_>>();
|
||||||
clean::RequiredMethod(_) => true,
|
let provided = t.items.iter().filter(|m| m.is_def()).collect::<Vec<_>>();
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<&clean::TraitMethod>>();
|
|
||||||
let provided = t.items.iter()
|
|
||||||
.filter(|m| {
|
|
||||||
match **m {
|
|
||||||
clean::ProvidedMethod(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<&clean::TraitMethod>>();
|
|
||||||
|
|
||||||
if t.items.len() == 0 {
|
if t.items.len() == 0 {
|
||||||
try!(write!(w, "{{ }}"));
|
try!(write!(w, "{{ }}"));
|
||||||
} else {
|
} else {
|
||||||
try!(write!(w, "{{\n"));
|
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() {
|
for m in required.iter() {
|
||||||
try!(write!(w, " "));
|
try!(write!(w, " "));
|
||||||
try!(render_method(w, m.item()));
|
try!(render_method(w, m.item()));
|
||||||
@ -1738,6 +1734,17 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::TraitMethod)
|
|||||||
Ok(())
|
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
|
// Output the documentation for each function individually
|
||||||
if required.len() > 0 {
|
if required.len() > 0 {
|
||||||
try!(write!(w, "
|
try!(write!(w, "
|
||||||
@ -1792,7 +1799,7 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::TraitMethod)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
|
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,
|
g: &clean::Generics, selfty: &clean::SelfTy,
|
||||||
d: &clean::FnDecl) -> fmt::Result {
|
d: &clean::FnDecl) -> fmt::Result {
|
||||||
write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
|
write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
|
||||||
@ -1807,14 +1814,28 @@ fn fun(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
|
|||||||
decl = Method(selfty, d),
|
decl = Method(selfty, d),
|
||||||
where_clause = WhereClause(g))
|
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 {
|
match meth.inner {
|
||||||
clean::TyMethodItem(ref m) => {
|
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) => {
|
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
|
||||||
-> fmt::Result {
|
-> fmt::Result {
|
||||||
try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
|
match item.inner {
|
||||||
*item.name.as_ref().unwrap(),
|
clean::MethodItem(..) | clean::TyMethodItem(..) => {
|
||||||
ConciseStability(&item.stability)));
|
try!(write!(w, "<h4 id='method.{}' class='{}'>{}<code>",
|
||||||
try!(render_method(w, item));
|
*item.name.as_ref().unwrap(),
|
||||||
try!(write!(w, "</code></h4>\n"));
|
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() {
|
match item.doc_value() {
|
||||||
Some(s) if dox => {
|
Some(s) if dox => {
|
||||||
try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
|
try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
|
||||||
@ -2085,7 +2121,7 @@ fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(write!(w, "<div class='impl-methods'>"));
|
try!(write!(w, "<div class='impl-items'>"));
|
||||||
for trait_item in i.impl_.items.iter() {
|
for trait_item in i.impl_.items.iter() {
|
||||||
try!(doctraititem(w, trait_item, true));
|
try!(doctraititem(w, trait_item, true));
|
||||||
}
|
}
|
||||||
@ -2107,6 +2143,8 @@ fn render_default_methods(w: &mut fmt::Formatter,
|
|||||||
|
|
||||||
// If we've implemented a trait, then also emit documentation for all
|
// If we've implemented a trait, then also emit documentation for all
|
||||||
// default methods which weren't overridden in the implementation block.
|
// 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_ {
|
match i.impl_.trait_ {
|
||||||
Some(clean::ResolvedPath { did, .. }) => {
|
Some(clean::ResolvedPath { did, .. }) => {
|
||||||
try!({
|
try!({
|
||||||
|
@ -84,7 +84,7 @@ h2 {
|
|||||||
h3 {
|
h3 {
|
||||||
font-size: 1.3em;
|
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;
|
color: black;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin: 20px 0 15px 0;
|
margin: 20px 0 15px 0;
|
||||||
@ -94,15 +94,15 @@ h1.fqn {
|
|||||||
border-bottom: 1px dashed #D5D5D5;
|
border-bottom: 1px dashed #D5D5D5;
|
||||||
margin-top: 0;
|
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;
|
border-bottom: 1px solid #DDDDDD;
|
||||||
}
|
}
|
||||||
h3.impl, h3.method, h4.method {
|
h3.impl, h3.method, h4.method, h3.type, h4.type {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
h3.impl, h3.method {
|
h3.impl, h3.method, h3.type {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle {
|
h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle {
|
||||||
@ -235,6 +235,7 @@ nav.sub {
|
|||||||
.content .highlighted.fn { background-color: #c6afb3; }
|
.content .highlighted.fn { background-color: #c6afb3; }
|
||||||
.content .highlighted.method { background-color: #c6afb3; }
|
.content .highlighted.method { background-color: #c6afb3; }
|
||||||
.content .highlighted.tymethod { background-color: #c6afb3; }
|
.content .highlighted.tymethod { background-color: #c6afb3; }
|
||||||
|
.content .highlighted.type { background-color: #c6afb3; }
|
||||||
.content .highlighted.ffi { background-color: #c6afb3; }
|
.content .highlighted.ffi { background-color: #c6afb3; }
|
||||||
|
|
||||||
.docblock.short.nowrap {
|
.docblock.short.nowrap {
|
||||||
@ -307,7 +308,7 @@ nav.sub {
|
|||||||
}
|
}
|
||||||
.content .methods .docblock { margin-left: 40px; }
|
.content .methods .docblock { margin-left: 40px; }
|
||||||
|
|
||||||
.content .impl-methods .docblock { margin-left: 40px; }
|
.content .impl-items .docblock { margin-left: 40px; }
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
border-bottom: 1px solid #e0e0e0;
|
border-bottom: 1px solid #e0e0e0;
|
||||||
@ -442,7 +443,7 @@ h1 .stability {
|
|||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.impl-methods .stability, .methods .stability {
|
.impl-items .stability, .methods .stability {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
#![allow(unknown_features)]
|
#![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 arena;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
Loading…
Reference in New Issue
Block a user