1
Fork 0

Rustdoc: disambiguate Implementors when the type name is not unique

This commit is contained in:
Esteban Küber 2016-12-15 23:13:00 -08:00
parent 6483bdd860
commit 2841bf3bc7
2 changed files with 201 additions and 171 deletions

View file

@ -433,7 +433,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
print_all: bool) -> fmt::Result {
print_all: bool, use_absolute: bool) -> fmt::Result {
let last = path.segments.last().unwrap();
let rel_root = match &*path.segments[0].name {
"self" => Some("./".to_string()),
@ -467,7 +467,17 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
if w.alternate() {
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
} else {
write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
let path = if use_absolute {
match href(did) {
Some((_, _, fqp)) => format!("{}::{}",
fqp[..fqp.len()-1].join("::"),
HRef::new(did, fqp.last().unwrap())),
None => format!("{}", HRef::new(did, &last.name)),
}
} else {
format!("{}", HRef::new(did, &last.name))
};
write!(w, "{}{}", path, last.params)?;
}
Ok(())
}
@ -551,15 +561,14 @@ impl<'a> fmt::Display for HRef<'a> {
}
}
impl fmt::Display for clean::Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, full_path: bool) -> fmt::Result {
match *t {
clean::Generic(ref name) => {
f.write_str(name)
}
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
// Paths like T::Output and Self::Output should be rendered with all segments
resolved_path(f, did, path, is_generic)?;
resolved_path(f, did, path, is_generic, full_path)?;
tybounds(f, typarams)
}
clean::Infer => write!(f, "_"),
@ -718,7 +727,7 @@ impl fmt::Display for clean::Type {
write!(f, "{}::", self_type)?;
}
let path = clean::Path::singleton(name.clone());
resolved_path(f, did, &path, false)?;
resolved_path(f, did, &path, true, full_path)?;
// FIXME: `typarams` are not rendered, and this seems bad?
drop(typarams);
@ -735,10 +744,15 @@ impl fmt::Display for clean::Type {
panic!("should have been cleaned")
}
}
}
impl fmt::Display for clean::Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt_type(self, f, false)
}
}
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool, full: bool) -> fmt::Result {
let mut plain = String::new();
if f.alternate() {
@ -759,7 +773,7 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R
plain.push_str(&format!("{:#}", ty));
} else {
match *ty {
clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => {
let last = path.segments.last().unwrap();
fmt::Display::fmt(&last.name, f)?;
fmt::Display::fmt(&last.params, f)?;
@ -772,7 +786,7 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R
plain.push_str(" for ");
}
fmt::Display::fmt(&i.for_, f)?;
fmt_type(&i.for_, f, full)?;
plain.push_str(&format!("{:#}", i.for_));
fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
@ -781,13 +795,15 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R
impl fmt::Display for clean::Impl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt_impl(self, f, true)
fmt_impl(self, f, true, false)
}
}
// The difference from above is that trait is not hyperlinked.
pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt::Result {
fmt_impl(i, f, false)
pub fn fmt_impl_for_trait_page(i: &clean::Impl,
f: &mut fmt::Formatter,
disambiguate: bool) -> fmt::Result {
fmt_impl(i, f, false, disambiguate)
}
impl fmt::Display for clean::Arguments {
@ -978,7 +994,7 @@ impl fmt::Display for clean::Import {
impl fmt::Display for clean::ImportSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.did {
Some(did) => resolved_path(f, did, &self.path, true),
Some(did) => resolved_path(f, did, &self.path, true, false),
_ => {
for (i, seg) in self.path.segments.iter().enumerate() {
if i > 0 {

View file

@ -2111,9 +2111,23 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<ul class='item-list' id='implementors-list'>
")?;
if let Some(implementors) = cache.implementors.get(&it.def_id) {
for i in implementors {
for k in implementors.iter() {
write!(w, "<li><code>")?;
fmt_impl_for_trait_page(&i.impl_, w)?;
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
let mut dissambiguate = false;
for l in implementors.iter() {
match (k.impl_.for_.clone(), l.impl_.for_.clone()) {
(clean::Type::ResolvedPath {path: path_a, ..},
clean::Type::ResolvedPath {path: path_b, ..}) => {
if k.def_id != l.def_id && path_a.last_name() == path_b.last_name() {
dissambiguate = true;
}
}
_ => (),
}
}
fmt_impl_for_trait_page(&k.impl_, w, dissambiguate)?;
writeln!(w, "</code></li>")?;
}
}