Skip to content

Commit 3ade321

Browse files
committed
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.
2 parents 33768c4 + a337592 commit 3ade321

File tree

1 file changed

+51
-10
lines changed

1 file changed

+51
-10
lines changed

src/librustdoc/html/render.rs

+51-10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use std::io;
3939
use std::io::{fs, File, BufferedWriter};
4040
use std::str;
4141
use std::vec;
42+
use std::vec_ng::Vec;
4243
use collections::{HashMap, HashSet};
4344

4445
use sync::Arc;
@@ -160,6 +161,13 @@ pub struct Cache {
160161
priv search_index: ~[IndexItem],
161162
priv privmod: bool,
162163
priv public_items: NodeSet,
164+
165+
// In rare case where a structure is defined in one module but implemented
166+
// in another, if the implementing module is parsed before defining module,
167+
// then the fully qualified name of the structure isn't presented in `paths`
168+
// yet when its implementation methods are being indexed. Caches such methods
169+
// and their parent id here and indexes them at the end of crate parsing.
170+
priv orphan_methods: Vec<(ast::NodeId, clean::Item)>,
163171
}
164172

165173
/// 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<()> {
249257
extern_locations: HashMap::new(),
250258
privmod: false,
251259
public_items: public_items,
260+
orphan_methods: Vec::new(),
252261
}
253262
});
254263
cache.stack.push(krate.name.clone());
255264
krate = cache.fold_crate(krate);
265+
{
266+
// Attach all orphan methods to the type's definition if the type
267+
// has since been learned.
268+
let Cache { search_index: ref mut index,
269+
orphan_methods: ref meths, paths: ref paths, ..} = cache;
270+
for &(ref pid, ref item) in meths.iter() {
271+
match paths.find(pid) {
272+
Some(&(ref fqp, _)) => {
273+
index.push(IndexItem {
274+
ty: shortty(item),
275+
name: item.name.clone().unwrap(),
276+
path: fqp.slice_to(fqp.len() - 1).connect("::"),
277+
desc: shorter(item.doc_value()).to_owned(),
278+
parent: Some(*pid),
279+
});
280+
},
281+
None => {}
282+
}
283+
};
284+
}
256285

257286
// Add all the static files
258287
let mut dst = cx.dst.join(krate.name.as_slice());
@@ -527,26 +556,33 @@ impl DocFolder for Cache {
527556
clean::TyMethodItem(..) |
528557
clean::StructFieldItem(..) |
529558
clean::VariantItem(..) => {
530-
Some((Some(*self.parent_stack.last().unwrap()),
531-
self.stack.slice_to(self.stack.len() - 1)))
559+
(Some(*self.parent_stack.last().unwrap()),
560+
Some(self.stack.slice_to(self.stack.len() - 1)))
532561

533562
}
534563
clean::MethodItem(..) => {
535564
if self.parent_stack.len() == 0 {
536-
None
565+
(None, None)
537566
} else {
538567
let last = self.parent_stack.last().unwrap();
539-
let amt = match self.paths.find(last) {
540-
Some(&(_, "trait")) => self.stack.len() - 1,
541-
Some(..) | None => self.stack.len(),
568+
let path = match self.paths.find(last) {
569+
Some(&(_, "trait")) =>
570+
Some(self.stack.slice_to(self.stack.len() - 1)),
571+
// The current stack not necessarily has correlation for
572+
// where the type was defined. On the other hand,
573+
// `paths` always has the right information if present.
574+
Some(&(ref fqp, "struct")) | Some(&(ref fqp, "enum")) =>
575+
Some(fqp.slice_to(fqp.len() - 1)),
576+
Some(..) => Some(self.stack.as_slice()),
577+
None => None
542578
};
543-
Some((Some(*last), self.stack.slice_to(amt)))
579+
(Some(*last), path)
544580
}
545581
}
546-
_ => Some((None, self.stack.as_slice()))
582+
_ => (None, Some(self.stack.as_slice()))
547583
};
548584
match parent {
549-
Some((parent, path)) if !self.privmod => {
585+
(parent, Some(path)) if !self.privmod => {
550586
self.search_index.push(IndexItem {
551587
ty: shortty(&item),
552588
name: s.to_owned(),
@@ -555,7 +591,12 @@ impl DocFolder for Cache {
555591
parent: parent,
556592
});
557593
}
558-
Some(..) | None => {}
594+
(Some(parent), None) if !self.privmod => {
595+
// We have a parent, but we don't know where they're
596+
// defined yet. Wait for later to index this item.
597+
self.orphan_methods.push((parent, item.clone()))
598+
}
599+
_ => {}
559600
}
560601
}
561602
None => {}

0 commit comments

Comments
 (0)