diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index dcc388a476204..e985de4d2f578 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -39,6 +39,7 @@ use std::io;
use std::io::{fs, File, BufferedWriter};
use std::str;
use std::vec;
+use std::vec_ng::Vec;
use collections::{HashMap, HashSet};
use sync::Arc;
@@ -160,6 +161,13 @@ pub struct Cache {
priv search_index: ~[IndexItem],
priv privmod: bool,
priv public_items: NodeSet,
+
+ // In rare case where a structure is defined in one module but implemented
+ // in another, if the implementing module is parsed before defining module,
+ // then the fully qualified name of the structure isn't presented in `paths`
+ // yet when its implementation methods are being indexed. Caches such methods
+ // and their parent id here and indexes them at the end of crate parsing.
+ priv orphan_methods: Vec<(ast::NodeId, clean::Item)>,
}
/// Helper struct to render all source code to HTML pages
@@ -249,10 +257,31 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
extern_locations: HashMap::new(),
privmod: false,
public_items: public_items,
+ orphan_methods: Vec::new(),
}
});
cache.stack.push(krate.name.clone());
krate = cache.fold_crate(krate);
+ {
+ // Attach all orphan methods to the type's definition if the type
+ // has since been learned.
+ let Cache { search_index: ref mut index,
+ orphan_methods: ref meths, paths: ref paths, ..} = cache;
+ for &(ref pid, ref item) in meths.iter() {
+ match paths.find(pid) {
+ Some(&(ref fqp, _)) => {
+ index.push(IndexItem {
+ ty: shortty(item),
+ name: item.name.clone().unwrap(),
+ path: fqp.slice_to(fqp.len() - 1).connect("::"),
+ desc: shorter(item.doc_value()).to_owned(),
+ parent: Some(*pid),
+ });
+ },
+ None => {}
+ }
+ };
+ }
// Add all the static files
let mut dst = cx.dst.join(krate.name.as_slice());
@@ -527,26 +556,33 @@ impl DocFolder for Cache {
clean::TyMethodItem(..) |
clean::StructFieldItem(..) |
clean::VariantItem(..) => {
- Some((Some(*self.parent_stack.last().unwrap()),
- self.stack.slice_to(self.stack.len() - 1)))
+ (Some(*self.parent_stack.last().unwrap()),
+ Some(self.stack.slice_to(self.stack.len() - 1)))
}
clean::MethodItem(..) => {
if self.parent_stack.len() == 0 {
- None
+ (None, None)
} else {
let last = self.parent_stack.last().unwrap();
- let amt = match self.paths.find(last) {
- Some(&(_, "trait")) => self.stack.len() - 1,
- Some(..) | None => self.stack.len(),
+ let path = match self.paths.find(last) {
+ Some(&(_, "trait")) =>
+ Some(self.stack.slice_to(self.stack.len() - 1)),
+ // The current stack not necessarily has correlation for
+ // where the type was defined. On the other hand,
+ // `paths` always has the right information if present.
+ Some(&(ref fqp, "struct")) | Some(&(ref fqp, "enum")) =>
+ Some(fqp.slice_to(fqp.len() - 1)),
+ Some(..) => Some(self.stack.as_slice()),
+ None => None
};
- Some((Some(*last), self.stack.slice_to(amt)))
+ (Some(*last), path)
}
}
- _ => Some((None, self.stack.as_slice()))
+ _ => (None, Some(self.stack.as_slice()))
};
match parent {
- Some((parent, path)) if !self.privmod => {
+ (parent, Some(path)) if !self.privmod => {
self.search_index.push(IndexItem {
ty: shortty(&item),
name: s.to_owned(),
@@ -555,7 +591,12 @@ impl DocFolder for Cache {
parent: parent,
});
}
- Some(..) | None => {}
+ (Some(parent), None) if !self.privmod => {
+ // We have a parent, but we don't know where they're
+ // defined yet. Wait for later to index this item.
+ self.orphan_methods.push((parent, item.clone()))
+ }
+ _ => {}
}
}
None => {}