Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rustdoc - display since version for stable items #30686

Merged
merged 1 commit into from
Feb 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,14 @@ impl Item {
_ => String::new(),
}
}

pub fn stable_since(&self) -> Option<&str> {
if let Some(ref s) = self.stability {
return Some(&s.since[..]);
}

None
}
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
Expand Down
98 changes: 71 additions & 27 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
generics = f.generics,
where_clause = WhereClause(&f.generics),
decl = f.decl));
try!(render_stability_since_raw(w, it.stable_since(), None));
document(w, cx, it)
}

Expand Down Expand Up @@ -1992,15 +1993,17 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
// Trait documentation
try!(document(w, cx, it));

fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item)
fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item)
-> fmt::Result {
let name = m.name.as_ref().unwrap();
let id = derive_id(format!("{}.{}", shortty(m), name));
try!(write!(w, "<h3 id='{id}' class='method stab {stab}'><code>",
id = id,
stab = m.stability_class()));
try!(render_assoc_item(w, m, AssocItemLink::Anchor));
try!(write!(w, "</code></h3>"));
try!(write!(w, "</code>"));
try!(render_stability_since(w, m, t));
try!(write!(w, "</h3>"));
try!(document(w, cx, m));
Ok(())
}
Expand All @@ -2011,7 +2014,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<div class='methods'>
"));
for t in &types {
try!(trait_item(w, cx, *t));
try!(trait_item(w, cx, *t, it));
}
try!(write!(w, "</div>"));
}
Expand All @@ -2022,7 +2025,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<div class='methods'>
"));
for t in &consts {
try!(trait_item(w, cx, *t));
try!(trait_item(w, cx, *t, it));
}
try!(write!(w, "</div>"));
}
Expand All @@ -2034,7 +2037,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<div class='methods'>
"));
for m in &required {
try!(trait_item(w, cx, *m));
try!(trait_item(w, cx, *m, it));
}
try!(write!(w, "</div>"));
}
Expand All @@ -2044,13 +2047,13 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<div class='methods'>
"));
for m in &provided {
try!(trait_item(w, cx, *m));
try!(trait_item(w, cx, *m, it));
}
try!(write!(w, "</div>"));
}

// If there are methods directly on this trait object, render them here.
try!(render_assoc_items(w, cx, it.def_id, AssocItemRender::All));
try!(render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All));

let cache = cache();
try!(write!(w, "
Expand Down Expand Up @@ -2106,6 +2109,29 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
Ok(())
}

fn render_stability_since_raw<'a>(w: &mut fmt::Formatter,
ver: Option<&'a str>,
containing_ver: Option<&'a str>) -> fmt::Result {
if containing_ver != ver {
match ver {
Some(v) =>
if v.len() > 0 {
try!(write!(w, "<span class=\"since\">{}</span>",
v))
},
None => {}
}
}

Ok(())
}

fn render_stability_since(w: &mut fmt::Formatter,
item: &clean::Item,
containing_item: &clean::Item) -> fmt::Result {
render_stability_since_raw(w, item.stable_since(), containing_item.stable_since())
}

fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
link: AssocItemLink) -> fmt::Result {
fn method(w: &mut fmt::Formatter,
Expand Down Expand Up @@ -2178,6 +2204,7 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
"",
true));
try!(write!(w, "</pre>"));
try!(render_stability_since_raw(w, it.stable_since(), None));

try!(document(w, cx, it));
let mut fields = s.fields.iter().filter(|f| {
Expand All @@ -2202,7 +2229,7 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
try!(write!(w, "</table>"));
}
}
render_assoc_items(w, cx, it.def_id, AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
}

fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
Expand Down Expand Up @@ -2257,10 +2284,11 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
try!(write!(w, "}}"));
}
try!(write!(w, "</pre>"));
try!(render_stability_since_raw(w, it.stable_since(), None));

try!(document(w, cx, it));
if !e.variants.is_empty() {
try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table>"));
try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table class='variants_table'>"));
for variant in &e.variants {
try!(write!(w, "<tr><td id='variant.{name}'><code>{name}</code></td><td>",
name = variant.name.as_ref().unwrap()));
Expand Down Expand Up @@ -2296,12 +2324,14 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
}
_ => ()
}
try!(write!(w, "</td><td>"));
try!(render_stability_since(w, variant, it));
try!(write!(w, "</td></tr>"));
}
try!(write!(w, "</table>"));

}
try!(render_assoc_items(w, cx, it.def_id, AssocItemRender::All));
try!(render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All));
Ok(())
}

Expand Down Expand Up @@ -2397,6 +2427,7 @@ enum AssocItemRender<'a> {

fn render_assoc_items(w: &mut fmt::Formatter,
cx: &Context,
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender) -> fmt::Result {
let c = cache();
Expand All @@ -2420,7 +2451,8 @@ fn render_assoc_items(w: &mut fmt::Formatter,
}
};
for i in &non_trait {
try!(render_impl(w, cx, i, AssocItemLink::Anchor, render_header));
try!(render_impl(w, cx, i, AssocItemLink::Anchor, render_header,
containing_item.stable_since()));
}
}
if let AssocItemRender::DerefFor { .. } = what {
Expand All @@ -2436,7 +2468,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
}
});
if let Some(impl_) = deref_impl {
try!(render_deref_methods(w, cx, impl_));
try!(render_deref_methods(w, cx, impl_, containing_item));
}
try!(write!(w, "<h2 id='implementations'>Trait \
Implementations</h2>"));
Expand All @@ -2445,22 +2477,25 @@ fn render_assoc_items(w: &mut fmt::Formatter,
});
for i in &manual {
let did = i.trait_did().unwrap();
try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true));
try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true,
containing_item.stable_since()));
}
if !derived.is_empty() {
try!(write!(w, "<h3 id='derived_implementations'>\
Derived Implementations \
</h3>"));
for i in &derived {
let did = i.trait_did().unwrap();
try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true));
try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true,
containing_item.stable_since()));
}
}
}
Ok(())
}

fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl) -> fmt::Result {
fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
container_item: &clean::Item) -> fmt::Result {
let deref_type = impl_.impl_.trait_.as_ref().unwrap();
let target = impl_.impl_.items.iter().filter_map(|item| {
match item.inner {
Expand All @@ -2470,12 +2505,12 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl) -> f
}).next().expect("Expected associated type binding");
let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target };
match *target {
clean::ResolvedPath { did, .. } => render_assoc_items(w, cx, did, what),
clean::ResolvedPath { did, .. } => render_assoc_items(w, cx, container_item, did, what),
_ => {
if let Some(prim) = target.primitive_type() {
if let Some(c) = cache().primitive_locations.get(&prim) {
let did = DefId { krate: *c, index: prim.to_def_index() };
try!(render_assoc_items(w, cx, did, what));
try!(render_assoc_items(w, cx, container_item, did, what));
}
}
Ok(())
Expand All @@ -2487,24 +2522,30 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl) -> f
// otherwise. If render_header is false, we will avoid rendering static
// methods, since they are not accessible for the type implementing `Deref`
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
render_header: bool) -> fmt::Result {
render_header: bool, outer_version: Option<&str>) -> fmt::Result {
if render_header {
try!(write!(w, "<h3 class='impl'><code>{}</code></h3>", i.impl_));
try!(write!(w, "<h3 class='impl'><code>{}</code>", i.impl_));
let since = i.stability.as_ref().map(|s| &s.since[..]);
try!(render_stability_since_raw(w, since, outer_version));
try!(write!(w, "</h3>"));
if let Some(ref dox) = i.dox {
try!(write!(w, "<div class='docblock'>{}</div>", Markdown(dox)));
}
}

fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
link: AssocItemLink, render_static: bool) -> fmt::Result {
link: AssocItemLink, render_static: bool,
outer_version: Option<&str>) -> fmt::Result {
let name = item.name.as_ref().unwrap();
match item.inner {
clean::MethodItem(..) | clean::TyMethodItem(..) => {
// Only render when the method is not static or we allow static methods
if !is_static_method(item) || render_static {
let id = derive_id(format!("method.{}", name));
try!(write!(w, "<h4 id='{}' class='{}'><code>", id, shortty(item)));
try!(render_assoc_item(w, item, link));
try!(write!(w, "<h4 id='{}' class='{}'>", id, shortty(item)));
try!(render_stability_since_raw(w, item.stable_since(), outer_version));
try!(write!(w, "<code>"));
try!(render_assoc_item(w, item, link));
try!(write!(w, "</code></h4>\n"));
}
}
Expand Down Expand Up @@ -2556,23 +2597,25 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi

try!(write!(w, "<div class='impl-items'>"));
for trait_item in &i.impl_.items {
try!(doctraititem(w, cx, trait_item, link, render_header));
try!(doctraititem(w, cx, trait_item, link, render_header, outer_version));
}

fn render_default_items(w: &mut fmt::Formatter,
cx: &Context,
did: DefId,
t: &clean::Trait,
i: &clean::Impl,
render_static: bool) -> fmt::Result {
render_static: bool,
outer_version: Option<&str>) -> fmt::Result {
for trait_item in &t.items {
let n = trait_item.name.clone();
match i.items.iter().find(|m| { m.name == n }) {
Some(..) => continue,
None => {}
}

try!(doctraititem(w, cx, trait_item, AssocItemLink::GotoSource(did), render_static));
try!(doctraititem(w, cx, trait_item, AssocItemLink::GotoSource(did), render_static,
outer_version));
}
Ok(())
}
Expand All @@ -2583,7 +2626,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
// for them work.
if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ {
if let Some(t) = cache().traits.get(&did) {
try!(render_default_items(w, cx, did, t, &i.impl_, render_header));
try!(render_default_items(w, cx, did, t, &i.impl_, render_header, outer_version));

}
}
Expand Down Expand Up @@ -2675,14 +2718,15 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
try!(w.write_str(&highlight::highlight(&t.source,
Some("macro"),
None)));
try!(render_stability_since_raw(w, it.stable_since(), None));
document(w, cx, it)
}

fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
it: &clean::Item,
_p: &clean::PrimitiveType) -> fmt::Result {
try!(document(w, cx, it));
render_assoc_items(w, cx, it.def_id, AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
}

fn get_basic_keywords() -> &'static str {
Expand Down
15 changes: 15 additions & 0 deletions src/librustdoc/html/static/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,21 @@ em.stab p {
opacity: 0.65;
}

span.since {
float: right;
font-weight: normal;
font-size: initial;
color: grey;
}

.variants_table {
width: 100%;
}

.variants_table tbody tr td:first-child {
width: 1%; /* make the variant name as small as possible */
}

td.summary-column {
width: 100%;
}
Expand Down