about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-03-07 17:16:52 -0800
committerbors <bors@rust-lang.org>2014-03-07 17:16:52 -0800
commit3ade32145b41eaca9a66e716fc1eb868a32d9d75 (patch)
tree85a0ac990d848f0efefdb1f0a3cdefba9415ed3b /src
parent33768c46ec980a911284d77804e5e45ead6530eb (diff)
parenta337592db66143e921b47020e27ad9af8589442b (diff)
downloadrust-3ade32145b41eaca9a66e716fc1eb868a32d9d75.tar.gz
rust-3ade32145b41eaca9a66e716fc1eb868a32d9d75.zip
auto merge of #12752 : edwardw/rust/rdoc, r=alexcrichton
A structure's definition and implementation may be cross-module. If the
implementing module is parsed before defining module, the fully
qualified name of the structure won't be present for the implementation
to use when being indexed. So caches such 'orphan' implementation and
indexes it at the end of crate parsing.

Closes #10284.
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/render.rs61
1 files changed, 51 insertions, 10 deletions
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index dcc388a4762..e985de4d2f5 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 => {}