// going on). If they're in different crates then the crate defining
// the trait will be interested in our implementation.
if imp.def_id.krate == did.krate { continue }
- write!(implementors, r#""{}","#, imp.impl_).unwrap();
+ write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
}
implementors.push_str("];");
component)?;
}
}
- write!(fmt, "<a class='{}' href=''>{}</a>",
+ write!(fmt, "<a class=\"{}\" href=''>{}</a>",
self.item.type_(), self.item.name.as_ref().unwrap())?;
write!(fmt, "</span>")?; // in-band
Ok(())
}
+fn md_render_assoc_item(item: &clean::Item) -> String {
+ match item.inner {
+ clean::AssociatedConstItem(ref ty, ref default) => {
+ if let Some(default) = default.as_ref() {
+ format!("```\n{}: {:?} = {}\n```\n\n", item.name.as_ref().unwrap(), ty, default)
+ } else {
+ format!("```\n{}: {:?}\n```\n\n", item.name.as_ref().unwrap(), ty)
+ }
+ }
+ _ => String::new(),
+ }
+}
+
+fn get_doc_value(item: &clean::Item) -> Option<&str> {
+ let x = item.doc_value();
+ if x.is_none() {
+ match item.inner {
+ clean::AssociatedConstItem(_, _) => Some(""),
+ _ => None,
+ }
+ } else {
+ x
+ }
+}
+
fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
- if let Some(s) = item.doc_value() {
- write!(w, "<div class='docblock'>{}</div>", Markdown(s))?;
+ if let Some(s) = get_doc_value(item) {
+ write!(w, "<div class='docblock'>{}</div>",
+ Markdown(&format!("{}{}", md_render_assoc_item(item), s)))?;
}
Ok(())
}
String::new()
};
- let mut unsafety_flag = "";
- if let clean::FunctionItem(ref func) = myitem.inner {
- if func.unsafety == hir::Unsafety::Unsafe {
- unsafety_flag = "<a title='unsafe function' href='#'><sup>⚠</sup></a>";
+ let unsafety_flag = match myitem.inner {
+ clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
+ if func.unsafety == hir::Unsafety::Unsafe => {
+ "<a title='unsafe function' href='#'><sup>⚠</sup></a>"
}
- }
+ _ => "",
+ };
let doc_value = myitem.doc_value().unwrap_or("");
write!(w, "
<tr class='{stab} module-item'>
- <td><a class='{class}' href='{href}'
- title='{title}'>{name}</a>{unsafety_flag}</td>
+ <td><a class=\"{class}\" href=\"{href}\"
+ title='{title_type} {title}'>{name}</a>{unsafety_flag}</td>
<td class='docblock-short'>
{stab_docs} {docs}
</td>
stab_docs = stab_docs,
docs = shorter(Some(&Markdown(doc_value).to_string())),
class = myitem.type_(),
- stab = myitem.stability_class(),
+ stab = myitem.stability_class().unwrap_or("".to_string()),
unsafety_flag = unsafety_flag,
href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()),
+ title_type = myitem.type_(),
title = full_path(cx, myitem))?;
}
}
&cx.shared.issue_tracker_base_url,
stab.issue) {
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
- format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
+ format!(" (<code>{} </code><a href=\"{}{}\">#{}</a>)",
Escape(&stab.feature), tracker_url, issue_no, issue_no),
(false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
format!(" (<a href=\"{}{}\">#{}</a>)", Escape(&tracker_url), issue_no,
if stab.unstable_reason.is_empty() {
stability.push(format!("<div class='stab unstable'>\
<span class=microscope>🔬</span> \
- This is a nightly-only experimental API. {}\
+ This is a nightly-only experimental API. {}\
</div>",
- unstable_extra));
+ unstable_extra));
} else {
let text = format!("<summary><span class=microscope>🔬</span> \
- This is a nightly-only experimental API. {}\
+ This is a nightly-only experimental API. {}\
</summary>{}",
unstable_extra, MarkdownHtml(&stab.unstable_reason));
stability.push(format!("<div class='stab unstable'><details>{}</details></div>",
fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
c: &clean::Constant) -> fmt::Result {
- write!(w, "<pre class='rust const'>{vis}const \
+ write!(w, "<pre class='rust const'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}const \
{name}: {typ}{init}</pre>",
vis = VisSpace(&it.visibility),
name = it.name.as_ref().unwrap(),
fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
s: &clean::Static) -> fmt::Result {
- write!(w, "<pre class='rust static'>{vis}static {mutability}\
+ write!(w, "<pre class='rust static'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}static {mutability}\
{name}: {typ}{init}</pre>",
vis = VisSpace(&it.visibility),
mutability = MutableSpace(s.mutability),
AbiSpace(f.abi),
it.name.as_ref().unwrap(),
f.generics).len();
- write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
+ write!(w, "<pre class='rust fn'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}{constness}{unsafety}{abi}fn \
{name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(&it.visibility),
constness = ConstnessSpace(vis_constness),
}
// Output the trait definition
- write!(w, "<pre class='rust trait'>{}{}trait {}{}{}{} ",
+ write!(w, "<pre class='rust trait'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{}{}trait {}{}{}{} ",
VisSpace(&it.visibility),
UnsafetySpace(t.unsafety),
it.name.as_ref().unwrap(),
<ul class='item-list' id='implementors-list'>
")?;
if let Some(implementors) = cache.implementors.get(&it.def_id) {
- let mut implementor_count: FxHashMap<&str, usize> = FxHashMap();
+ // The DefId is for the first Type found with that name. The bool is
+ // if any Types with the same name but different DefId have been found.
+ let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
for implementor in implementors {
- if let clean::Type::ResolvedPath {ref path, ..} = implementor.impl_.for_ {
- *implementor_count.entry(path.last_name()).or_insert(0) += 1;
+ match implementor.impl_.for_ {
+ clean::ResolvedPath { ref path, did, is_generic: false, .. } |
+ clean::BorrowedRef {
+ type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
+ ..
+ } => {
+ let &mut (prev_did, ref mut has_duplicates) =
+ implementor_dups.entry(path.last_name()).or_insert((did, false));
+ if prev_did != did {
+ *has_duplicates = true;
+ }
+ }
+ _ => {}
}
}
write!(w, "<li><code>")?;
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
- let use_absolute = if let clean::Type::ResolvedPath {
- ref path, ..
- } = implementor.impl_.for_ {
- implementor_count[path.last_name()] > 1
- } else {
- false
+ let use_absolute = match implementor.impl_.for_ {
+ clean::ResolvedPath { ref path, is_generic: false, .. } |
+ clean::BorrowedRef {
+ type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
+ ..
+ } => implementor_dups[path.last_name()].1,
+ _ => false,
};
fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
writeln!(w, "</code></li>")?;
fn assoc_const(w: &mut fmt::Formatter,
it: &clean::Item,
ty: &clean::Type,
- default: Option<&String>,
+ _default: Option<&String>,
link: AssocItemLink) -> fmt::Result {
- write!(w, "const <a href='{}' class='constant'>{}</a>",
+ write!(w, "const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
naive_assoc_href(it, link),
- it.name.as_ref().unwrap())?;
-
- write!(w, ": {}", ty)?;
- if let Some(default) = default {
- write!(w, " = {}", Escape(default))?;
- }
+ it.name.as_ref().unwrap(),
+ ty)?;
Ok(())
}
bounds: &Vec<clean::TyParamBound>,
default: Option<&clean::Type>,
link: AssocItemLink) -> fmt::Result {
- write!(w, "type <a href='{}' class='type'>{}</a>",
+ write!(w, "type <a href='{}' class=\"type\">{}</a>",
naive_assoc_href(it, link),
it.name.as_ref().unwrap())?;
if !bounds.is_empty() {
let ns_id = derive_id(format!("{}.{}",
field.name.as_ref().unwrap(),
ItemType::StructField.name_space()));
- write!(w, "<span id='{id}' class='{item_type}'>
+ write!(w, "<span id='{id}' class=\"{item_type}\">
<span id='{ns_id}' class='invisible'>
<code>{name}: {ty}</code>
- </span></span><span class='stab {stab}'></span>",
+ </span></span>",
item_type = ItemType::StructField,
id = id,
ns_id = ns_id,
- stab = field.stability_class(),
name = field.name.as_ref().unwrap(),
ty = ty)?;
+ if let Some(stability_class) = field.stability_class() {
+ write!(w, "<span class='stab {stab}'></span>",
+ stab = stability_class)?;
+ }
document(w, cx, field)?;
}
}
if fields.peek().is_some() {
write!(w, "<h2 class='fields'>Fields</h2>")?;
for (field, ty) in fields {
- write!(w, "<span id='{shortty}.{name}' class='{shortty}'><code>{name}: {ty}</code>
- </span><span class='stab {stab}'></span>",
+ write!(w, "<span id='{shortty}.{name}' class=\"{shortty}\"><code>{name}: {ty}</code>
+ </span>",
shortty = ItemType::StructField,
- stab = field.stability_class(),
name = field.name.as_ref().unwrap(),
ty = ty)?;
+ if let Some(stability_class) = field.stability_class() {
+ write!(w, "<span class='stab {stab}'></span>",
+ stab = stability_class)?;
+ }
document(w, cx, field)?;
}
}
if render_method_item {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'>", ns_id)?;
write!(w, "<code>")?;
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
clean::TypedefItem(ref tydef, _) => {
let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
clean::AssociatedConstItem(ref ty, ref default) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
clean::ConstantItem(ref c) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
clean::AssociatedTypeItem(ref bounds, ref default) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
// We need the stability of the item from the trait
// because impls can't have a stability.
document_stability(w, cx, it)?;
- if item.doc_value().is_some() {
+ if get_doc_value(item).is_some() {
document_full(w, item)?;
} else {
// In case the item isn't documented,
fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t: &clean::Typedef) -> fmt::Result {
let indent = format!("type {}{:#} ", it.name.as_ref().unwrap(), t.generics).len();
- write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
+ write!(w, "<pre class='rust typedef'>")?;
+ render_attributes(w, it)?;
+ write!(w, "type {}{}{where_clause} = {type_};</pre>",
it.name.as_ref().unwrap(),
t.generics,
where_clause = WhereClause(&t.generics, indent),