fix dead link for method in trait of blanket impl from third party crate
This commit is contained in:
parent
238fd72880
commit
53447d81d0
3 changed files with 47 additions and 31 deletions
|
@ -459,7 +459,7 @@ impl Item {
|
||||||
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
|
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
|
||||||
match did {
|
match did {
|
||||||
Some(did) => {
|
Some(did) => {
|
||||||
if let Some((mut href, ..)) = href(did.clone(), cx) {
|
if let Ok((mut href, ..)) = href(did.clone(), cx) {
|
||||||
if let Some(ref fragment) = *fragment {
|
if let Some(ref fragment) = *fragment {
|
||||||
href.push('#');
|
href.push('#');
|
||||||
href.push_str(fragment);
|
href.push_str(fragment);
|
||||||
|
|
|
@ -472,7 +472,18 @@ impl clean::GenericArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<String>)> {
|
// Possible errors when computing href link source for a `DefId`
|
||||||
|
crate enum HrefError {
|
||||||
|
// `DefId` is in an unknown location. This seems to happen when building without dependencies
|
||||||
|
// but a trait from a dependency is still visible
|
||||||
|
UnknownLocation,
|
||||||
|
// Unavailable because private
|
||||||
|
Unavailable,
|
||||||
|
// Not in external cache, href link should be in same page
|
||||||
|
NotInExternalCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<String>), HrefError> {
|
||||||
let cache = &cx.cache();
|
let cache = &cx.cache();
|
||||||
let relative_to = &cx.current;
|
let relative_to = &cx.current;
|
||||||
fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
|
fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
|
||||||
|
@ -480,7 +491,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
|
||||||
}
|
}
|
||||||
|
|
||||||
if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
|
if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
|
||||||
return None;
|
return Err(HrefError::Unavailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
|
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
|
||||||
|
@ -489,22 +500,25 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
|
||||||
href_relative_parts(module_fqp, relative_to)
|
href_relative_parts(module_fqp, relative_to)
|
||||||
}),
|
}),
|
||||||
None => {
|
None => {
|
||||||
let &(ref fqp, shortty) = cache.external_paths.get(&did)?;
|
if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) {
|
||||||
let module_fqp = to_module_fqp(shortty, fqp);
|
let module_fqp = to_module_fqp(shortty, fqp);
|
||||||
(
|
(
|
||||||
fqp,
|
fqp,
|
||||||
shortty,
|
shortty,
|
||||||
match cache.extern_locations[&did.krate] {
|
match cache.extern_locations[&did.krate] {
|
||||||
ExternalLocation::Remote(ref s) => {
|
ExternalLocation::Remote(ref s) => {
|
||||||
let s = s.trim_end_matches('/');
|
let s = s.trim_end_matches('/');
|
||||||
let mut s = vec![&s[..]];
|
let mut s = vec![&s[..]];
|
||||||
s.extend(module_fqp[..].iter().map(String::as_str));
|
s.extend(module_fqp[..].iter().map(String::as_str));
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
|
ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
|
||||||
ExternalLocation::Unknown => return None,
|
ExternalLocation::Unknown => return Err(HrefError::UnknownLocation),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return Err(HrefError::NotInExternalCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let last = &fqp.last().unwrap()[..];
|
let last = &fqp.last().unwrap()[..];
|
||||||
|
@ -518,7 +532,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
|
||||||
url_parts.push(&filename);
|
url_parts.push(&filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some((url_parts.join("/"), shortty, fqp.to_vec()))
|
Ok((url_parts.join("/"), shortty, fqp.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Both paths should only be modules.
|
/// Both paths should only be modules.
|
||||||
|
@ -567,7 +581,7 @@ fn resolved_path<'a, 'cx: 'a>(
|
||||||
write!(w, "{}{:#}", &last.name, last.args.print(cx))?;
|
write!(w, "{}{:#}", &last.name, last.args.print(cx))?;
|
||||||
} else {
|
} else {
|
||||||
let path = if use_absolute {
|
let path = if use_absolute {
|
||||||
if let Some((_, _, fqp)) = href(did, cx) {
|
if let Ok((_, _, fqp)) = href(did, cx) {
|
||||||
format!(
|
format!(
|
||||||
"{}::{}",
|
"{}::{}",
|
||||||
fqp[..fqp.len() - 1].join("::"),
|
fqp[..fqp.len() - 1].join("::"),
|
||||||
|
@ -675,7 +689,7 @@ crate fn anchor<'a, 'cx: 'a>(
|
||||||
) -> impl fmt::Display + 'a {
|
) -> impl fmt::Display + 'a {
|
||||||
let parts = href(did.into(), cx);
|
let parts = href(did.into(), cx);
|
||||||
display_fn(move |f| {
|
display_fn(move |f| {
|
||||||
if let Some((url, short_ty, fqp)) = parts {
|
if let Ok((url, short_ty, fqp)) = parts {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
|
r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
|
||||||
|
@ -907,7 +921,7 @@ fn fmt_type<'cx>(
|
||||||
// look at).
|
// look at).
|
||||||
box clean::ResolvedPath { did, .. } => {
|
box clean::ResolvedPath { did, .. } => {
|
||||||
match href(did.into(), cx) {
|
match href(did.into(), cx) {
|
||||||
Some((ref url, _, ref path)) if !f.alternate() => {
|
Ok((ref url, _, ref path)) if !f.alternate() => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
|
"<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
|
||||||
|
|
|
@ -62,7 +62,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode};
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::format::{
|
use crate::html::format::{
|
||||||
href, print_abi_with_space, print_constness_with_space, print_default_space,
|
href, print_abi_with_space, print_constness_with_space, print_default_space,
|
||||||
print_generic_bounds, print_where_clause, Buffer, PrintWithSpace,
|
print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace,
|
||||||
};
|
};
|
||||||
use crate::html::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine};
|
use crate::html::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine};
|
||||||
|
|
||||||
|
@ -856,8 +856,8 @@ fn render_assoc_item(
|
||||||
) {
|
) {
|
||||||
let name = meth.name.as_ref().unwrap();
|
let name = meth.name.as_ref().unwrap();
|
||||||
let href = match link {
|
let href = match link {
|
||||||
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
|
AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)),
|
||||||
AssocItemLink::Anchor(None) => format!("#{}.{}", meth.type_(), name),
|
AssocItemLink::Anchor(None) => Some(format!("#{}.{}", meth.type_(), name)),
|
||||||
AssocItemLink::GotoSource(did, provided_methods) => {
|
AssocItemLink::GotoSource(did, provided_methods) => {
|
||||||
// We're creating a link from an impl-item to the corresponding
|
// We're creating a link from an impl-item to the corresponding
|
||||||
// trait-item and need to map the anchored type accordingly.
|
// trait-item and need to map the anchored type accordingly.
|
||||||
|
@ -867,9 +867,11 @@ fn render_assoc_item(
|
||||||
ItemType::TyMethod
|
ItemType::TyMethod
|
||||||
};
|
};
|
||||||
|
|
||||||
href(did.expect_def_id(), cx)
|
match href(did.expect_def_id(), cx) {
|
||||||
.map(|p| format!("{}#{}.{}", p.0, ty, name))
|
Ok(p) => Some(format!("{}#{}.{}", p.0, ty, name)),
|
||||||
.unwrap_or_else(|| format!("#{}.{}", ty, name))
|
Err(HrefError::UnknownLocation) => None,
|
||||||
|
Err(_) => Some(format!("#{}.{}", ty, name)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
|
let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
|
||||||
|
@ -904,7 +906,7 @@ fn render_assoc_item(
|
||||||
w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
|
w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
|
"{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a {href} class=\"fnname\">{name}</a>\
|
||||||
{generics}{decl}{notable_traits}{where_clause}",
|
{generics}{decl}{notable_traits}{where_clause}",
|
||||||
indent = indent_str,
|
indent = indent_str,
|
||||||
vis = vis,
|
vis = vis,
|
||||||
|
@ -913,7 +915,7 @@ fn render_assoc_item(
|
||||||
unsafety = unsafety,
|
unsafety = unsafety,
|
||||||
defaultness = defaultness,
|
defaultness = defaultness,
|
||||||
abi = abi,
|
abi = abi,
|
||||||
href = href,
|
href = href.map(|href| format!("href=\"{}\"", href)).unwrap_or_else(|| "".to_string()),
|
||||||
name = name,
|
name = name,
|
||||||
generics = g.print(cx),
|
generics = g.print(cx),
|
||||||
decl = d.full_print(header_len, indent, header.asyncness, cx),
|
decl = d.full_print(header_len, indent, header.asyncness, cx),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue