Skip to content

Commit 89aa042

Browse files
committedMay 6, 2016
rustdoc: add "src" links to individual impls
Since these impls can be scattered around quite a bit, it is nice to be able to jump to the location where individual methods and trait impls are defined. Fixes: #30416
1 parent 3157691 commit 89aa042

File tree

1 file changed

+59
-39
lines changed

1 file changed

+59
-39
lines changed
 

‎src/librustdoc/html/render.rs

+59-39
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,19 @@ pub struct Implementor {
145145
/// Metadata about implementations for a type.
146146
#[derive(Clone)]
147147
pub struct Impl {
148-
pub impl_: clean::Impl,
149-
pub dox: Option<String>,
150-
pub stability: Option<clean::Stability>,
148+
pub impl_item: clean::Item,
151149
}
152150

153151
impl Impl {
152+
fn inner_impl(&self) -> &clean::Impl {
153+
match self.impl_item.inner {
154+
clean::ImplItem(ref impl_) => impl_,
155+
_ => panic!("non-impl item found in impl")
156+
}
157+
}
158+
154159
fn trait_did(&self) -> Option<DefId> {
155-
self.impl_.trait_.def_id()
160+
self.inner_impl().trait_.def_id()
156161
}
157162
}
158163

@@ -1189,31 +1194,34 @@ impl DocFolder for Cache {
11891194
// Once we've recursively found all the generics, then hoard off all the
11901195
// implementations elsewhere
11911196
let ret = self.fold_item_recur(item).and_then(|item| {
1192-
if let clean::Item { attrs, inner: clean::ImplItem(i), .. } = item {
1197+
if let clean::Item { inner: clean::ImplItem(_), .. } = item {
11931198
// Figure out the id of this impl. This may map to a
11941199
// primitive rather than always to a struct/enum.
1195-
let did = match i.for_ {
1196-
clean::ResolvedPath { did, .. } |
1197-
clean::BorrowedRef {
1198-
type_: box clean::ResolvedPath { did, .. }, ..
1199-
} => {
1200-
Some(did)
1201-
}
1202-
ref t => {
1203-
t.primitive_type().and_then(|t| {
1204-
self.primitive_locations.get(&t).map(|n| {
1205-
let id = t.to_def_index();
1206-
DefId { krate: *n, index: id }
1200+
// Note: matching twice to restrict the lifetime of the `i` borrow.
1201+
let did = if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
1202+
match i.for_ {
1203+
clean::ResolvedPath { did, .. } |
1204+
clean::BorrowedRef {
1205+
type_: box clean::ResolvedPath { did, .. }, ..
1206+
} => {
1207+
Some(did)
1208+
}
1209+
ref t => {
1210+
t.primitive_type().and_then(|t| {
1211+
self.primitive_locations.get(&t).map(|n| {
1212+
let id = t.to_def_index();
1213+
DefId { krate: *n, index: id }
1214+
})
12071215
})
1208-
})
1216+
}
12091217
}
1218+
} else {
1219+
unreachable!()
12101220
};
12111221
if !self.seen_mod {
12121222
if let Some(did) = did {
12131223
self.impls.entry(did).or_insert(vec![]).push(Impl {
1214-
impl_: i,
1215-
dox: attrs.value("doc").map(|s|s.to_owned()),
1216-
stability: item.stability.clone(),
1224+
impl_item: item,
12171225
});
12181226
}
12191227
}
@@ -1510,11 +1518,15 @@ impl<'a> Item<'a> {
15101518
// located, then we return `None`.
15111519
} else {
15121520
let cache = cache();
1513-
let path = &cache.external_paths[&self.item.def_id];
1514-
let root = match cache.extern_locations[&self.item.def_id.krate] {
1515-
(_, Remote(ref s)) => s.to_string(),
1516-
(_, Local) => self.cx.root_path.clone(),
1517-
(_, Unknown) => return None,
1521+
let path = match cache.external_paths.get(&self.item.def_id) {
1522+
Some(path) => path,
1523+
None => return None,
1524+
};
1525+
let root = match cache.extern_locations.get(&self.item.def_id.krate) {
1526+
Some(&(_, Remote(ref s))) => s.to_string(),
1527+
Some(&(_, Local)) => self.cx.root_path.clone(),
1528+
Some(&(_, Unknown)) => return None,
1529+
None => return None,
15181530
};
15191531
Some(format!("{root}{path}/{file}?gotosrc={goto}",
15201532
root = root,
@@ -2449,7 +2461,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
24492461
None => return Ok(()),
24502462
};
24512463
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| {
2452-
i.impl_.trait_.is_none()
2464+
i.inner_impl().trait_.is_none()
24532465
});
24542466
if !non_trait.is_empty() {
24552467
let render_header = match what {
@@ -2473,19 +2485,19 @@ fn render_assoc_items(w: &mut fmt::Formatter,
24732485
}
24742486
if !traits.is_empty() {
24752487
let deref_impl = traits.iter().find(|t| {
2476-
t.impl_.trait_.def_id() == c.deref_trait_did
2488+
t.inner_impl().trait_.def_id() == c.deref_trait_did
24772489
});
24782490
if let Some(impl_) = deref_impl {
24792491
render_deref_methods(w, cx, impl_, containing_item)?;
24802492
}
24812493
write!(w, "<h2 id='implementations'>Trait \
24822494
Implementations</h2>")?;
24832495
let (derived, manual): (Vec<_>, Vec<&Impl>) = traits.iter().partition(|i| {
2484-
i.impl_.derived
2496+
i.inner_impl().derived
24852497
});
24862498
for i in &manual {
24872499
let did = i.trait_did().unwrap();
2488-
let assoc_link = AssocItemLink::GotoSource(did, &i.impl_.provided_trait_methods);
2500+
let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
24892501
render_impl(w, cx, i, assoc_link, true, containing_item.stable_since())?;
24902502
}
24912503
if !derived.is_empty() {
@@ -2494,7 +2506,8 @@ fn render_assoc_items(w: &mut fmt::Formatter,
24942506
</h3>")?;
24952507
for i in &derived {
24962508
let did = i.trait_did().unwrap();
2497-
let assoc_link = AssocItemLink::GotoSource(did, &i.impl_.provided_trait_methods);
2509+
let assoc_link = AssocItemLink::GotoSource(did,
2510+
&i.inner_impl().provided_trait_methods);
24982511
render_impl(w, cx, i, assoc_link, true, containing_item.stable_since())?;
24992512
}
25002513
}
@@ -2504,8 +2517,8 @@ fn render_assoc_items(w: &mut fmt::Formatter,
25042517

25052518
fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
25062519
container_item: &clean::Item) -> fmt::Result {
2507-
let deref_type = impl_.impl_.trait_.as_ref().unwrap();
2508-
let target = impl_.impl_.items.iter().filter_map(|item| {
2520+
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
2521+
let target = impl_.inner_impl().items.iter().filter_map(|item| {
25092522
match item.inner {
25102523
clean::TypedefItem(ref t, true) => Some(&t.type_),
25112524
_ => None,
@@ -2531,11 +2544,18 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
25312544
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
25322545
render_header: bool, outer_version: Option<&str>) -> fmt::Result {
25332546
if render_header {
2534-
write!(w, "<h3 class='impl'><code>{}</code>", i.impl_)?;
2535-
let since = i.stability.as_ref().map(|s| &s.since[..]);
2547+
write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
2548+
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
25362549
render_stability_since_raw(w, since, outer_version)?;
2537-
write!(w, "</h3>")?;
2538-
if let Some(ref dox) = i.dox {
2550+
write!(w, "</span><span class='out-of-band'>")?;
2551+
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).href() {
2552+
write!(w, "<a id='src-{}' class='srclink' \
2553+
href='{}' title='{}'>[src]</a>",
2554+
i.impl_item.def_id.index.as_usize(), l, "goto source code")?;
2555+
}
2556+
write!(w, "</span>")?;
2557+
write!(w, "</h3>\n")?;
2558+
if let Some(ref dox) = i.impl_item.attrs.value("doc") {
25392559
write!(w, "<div class='docblock'>{}</div>", Markdown(dox))?;
25402560
}
25412561
}
@@ -2601,7 +2621,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
26012621
}
26022622

26032623
write!(w, "<div class='impl-items'>")?;
2604-
for trait_item in &i.impl_.items {
2624+
for trait_item in &i.inner_impl().items {
26052625
doctraititem(w, cx, trait_item, link, render_header, false, outer_version)?;
26062626
}
26072627

@@ -2629,7 +2649,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
26292649
// default items which weren't overridden in the implementation block.
26302650
if let Some(did) = i.trait_did() {
26312651
if let Some(t) = cache().traits.get(&did) {
2632-
render_default_items(w, cx, t, &i.impl_, render_header, outer_version)?;
2652+
render_default_items(w, cx, t, &i.inner_impl(), render_header, outer_version)?;
26332653
}
26342654
}
26352655
write!(w, "</div>")?;

0 commit comments

Comments
 (0)
Please sign in to comment.