diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 320baf3318164c5bfeb3113762fb8615fe82b344..f4772d7adc3d38a45efbe14d82badde8ed34270f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2499,6 +2499,26 @@ fn get_binding(this: @mut Resolver, assert!(import_resolution.outstanding_references >= 1); import_resolution.outstanding_references -= 1; + // record what this import resolves to for later uses in documentation, + // this may resolve to either a value or a type, but for documentation + // purposes it's good enough to just favor one over the other. + match i.value_target { + Some(target) => { + self.def_map.insert(i.value_id, + target.bindings.value_def.get_ref().def); + } + None => {} + } + match i.type_target { + Some(target) => { + match target.bindings.type_def.get_ref().type_def { + Some(def) => { self.def_map.insert(i.type_id, def); } + None => {} + } + } + None => {} + } + debug!("(resolving single import) successfully resolved import"); return Success(()); } @@ -2626,6 +2646,14 @@ pub fn resolve_glob_import(@mut self, merge_import_resolution(name, name_bindings); } + // Record the destination of this import + match containing_module.def_id { + Some(did) => { + self.def_map.insert(id, DefMod(did)); + } + None => {} + } + debug!("(resolving glob import) successfully resolved import"); return Success(()); } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index 8cbe1eed55af40b6a76eafa8dfcc8a4064eb9cdd..291476c13904497ba3eb883e8a36625add60fd62 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -930,26 +930,45 @@ fn clean(&self) -> ViewItemInner { #[deriving(Clone, Encodable, Decodable)] pub enum ViewPath { - SimpleImport(~str, Path, ast::NodeId), - GlobImport(Path, ast::NodeId), - ImportList(Path, ~[ViewListIdent], ast::NodeId) + // use str = source; + SimpleImport(~str, ImportSource), + // use source::*; + GlobImport(ImportSource), + // use source::{a, b, c}; + ImportList(ImportSource, ~[ViewListIdent]), +} + +#[deriving(Clone, Encodable, Decodable)] +pub struct ImportSource { + path: Path, + did: Option, } impl Clean for ast::view_path { fn clean(&self) -> ViewPath { match self.node { - ast::view_path_simple(ref i, ref p, ref id) => SimpleImport(i.clean(), p.clean(), *id), - ast::view_path_glob(ref p, ref id) => GlobImport(p.clean(), *id), - ast::view_path_list(ref p, ref pl, ref id) => ImportList(p.clean(), pl.clean(), *id), + ast::view_path_simple(ref i, ref p, id) => + SimpleImport(i.clean(), resolve_use_source(p.clean(), id)), + ast::view_path_glob(ref p, id) => + GlobImport(resolve_use_source(p.clean(), id)), + ast::view_path_list(ref p, ref pl, id) => + ImportList(resolve_use_source(p.clean(), id), pl.clean()), } } } -pub type ViewListIdent = ~str; +#[deriving(Clone, Encodable, Decodable)] +pub struct ViewListIdent { + name: ~str, + source: Option, +} impl Clean for ast::path_list_ident { fn clean(&self) -> ViewListIdent { - self.node.name.clean() + ViewListIdent { + name: self.node.name.clean(), + source: resolve_def(self.node.id), + } } } @@ -1092,6 +1111,18 @@ fn resolve_type(t: &Type) -> Type { let cname = cratedata.name.to_owned(); External(cname + "::" + path, ty) } else { - ResolvedPath {path: path.clone(), typarams: tpbs.clone(), id: def_id.node} + ResolvedPath {path: path.clone(), typarams: tpbs, id: def_id.node} } } + +fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource { + ImportSource { + path: path, + did: resolve_def(id), + } +} + +fn resolve_def(id: ast::NodeId) -> Option { + let dm = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.def_map; + dm.find(&id).map_move(|&d| ast_util::def_id_of_def(d)) +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6f05b042dba1c847c8af1d4bfb1f23ce05e81862..7010e7fa4eab6a51de94ba65a3ced8ce9d1f65cf 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -97,7 +97,8 @@ fn fmt(path: &clean::Path, f: &mut fmt::Formatter) { } } -fn resolved_path(w: &mut io::Writer, id: ast::NodeId, path: &clean::Path) { +fn resolved_path(w: &mut io::Writer, id: ast::NodeId, + path: &clean::Path, print_all: bool) { // The generics will get written to both the title and link let mut generics = ~""; let last = path.segments.last(); @@ -119,47 +120,73 @@ fn resolved_path(w: &mut io::Writer, id: ast::NodeId, path: &clean::Path) { // Did someone say rightward-drift? do local_data::get(current_location_key) |loc| { let loc = loc.unwrap(); + + if print_all { + let mut root = match path.segments[0].name.as_slice() { + "super" => ~"../", + "self" => ~"", + _ => "../".repeat(loc.len() - 1), + }; + let amt = path.segments.len() - 1; + for seg in path.segments.slice_to(amt).iter() { + if "super" == seg.name || "self" == seg.name { + write!(w, "{}::", seg.name); + } else { + root.push_str(seg.name); + root.push_str("/"); + write!(w, "{}::", + root, + seg.name); + } + } + } + do local_data::get(cache_key) |cache| { do cache.unwrap().read |cache| { match cache.paths.find(&id) { // This is a documented path, link to it! Some(&(ref fqp, shortty)) => { let fqn = fqp.connect("::"); - let mut same = 0; - for (a, b) in loc.iter().zip(fqp.iter()) { - if *a == *b { - same += 1; - } else { - break; - } - } + let same = loc.iter().zip(fqp.iter()) + .take_while(|&(a, b)| *a == *b).len(); let mut url = ~""; - for _ in range(same, loc.len()) { + if "super" == path.segments[0].name { url.push_str("../"); + } else if "self" != path.segments[0].name { + url.push_str("../".repeat(loc.len() - same)); } - if same == fqp.len() { - url.push_str(shortty); - url.push_str("."); - url.push_str(*fqp.last()); - url.push_str(".html"); - } else { + if same < fqp.len() { let remaining = fqp.slice_from(same); let to_link = remaining.slice_to(remaining.len() - 1); for component in to_link.iter() { url.push_str(*component); url.push_str("/"); } - url.push_str(shortty); - url.push_str("."); - url.push_str(*remaining.last()); - url.push_str(".html"); } - + match shortty { + "mod" => { + url.push_str(*fqp.last()); + url.push_str("/index.html"); + } + _ => { + url.push_str(shortty); + url.push_str("."); + url.push_str(*fqp.last()); + url.push_str(".html"); + } + } write!(w, "{}{}", shortty, url, fqn, last.name, generics); } None => { + if print_all { + let amt = path.segments.len() - 1; + for seg in path.segments.iter().take(amt) { + write!(w, "{}::", seg.name); + } + } write!(w, "{}{}", last.name, generics); } }; @@ -178,9 +205,8 @@ fn fmt(g: &clean::Type, f: &mut fmt::Formatter) { } } } - clean::Unresolved(*) => unreachable!(), clean::ResolvedPath{id, typarams: ref typarams, path: ref path} => { - resolved_path(f.buf, id, path); + resolved_path(f.buf, id, path, false); match *typarams { Some(ref params) => { f.buf.write("<".as_bytes()); @@ -366,3 +392,63 @@ fn fmt(p: &PuritySpace, f: &mut fmt::Formatter) { } } } + +impl fmt::Default for clean::ViewPath { + fn fmt(v: &clean::ViewPath, f: &mut fmt::Formatter) { + match *v { + clean::SimpleImport(ref name, ref src) => { + if *name == src.path.segments.last().name { + write!(f.buf, "use {};", *src); + } else { + write!(f.buf, "use {} = {};", *name, *src); + } + } + clean::GlobImport(ref src) => { + write!(f.buf, "use {}::*;", *src); + } + clean::ImportList(ref src, ref names) => { + write!(f.buf, "use {}::\\{", *src); + for (i, n) in names.iter().enumerate() { + if i > 0 { write!(f.buf, ", "); } + write!(f.buf, "{}", *n); + } + write!(f.buf, "\\};"); + } + } + } +} + +impl fmt::Default for clean::ImportSource { + fn fmt(v: &clean::ImportSource, f: &mut fmt::Formatter) { + match v.did { + Some(did) if ast_util::is_local(did) => { + resolved_path(f.buf, did.node, &v.path, true); + } + _ => { + for (i, seg) in v.path.segments.iter().enumerate() { + if i > 0 { write!(f.buf, "::") } + write!(f.buf, "{}", seg.name); + } + } + } + } +} + +impl fmt::Default for clean::ViewListIdent { + fn fmt(v: &clean::ViewListIdent, f: &mut fmt::Formatter) { + match v.source { + Some(did) if ast_util::is_local(did) => { + let path = clean::Path { + global: false, + segments: ~[clean::PathSegment { + name: v.name.clone(), + lifetime: None, + types: ~[], + }] + }; + resolved_path(f.buf, did.node, &path, false); + } + _ => write!(f.buf, "{}", v.name), + } + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 070c0e5d9864289627c83431206e08f0734da6cc..790d9bef746ced62b919d69ae6539e3259fd57ea 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -288,7 +288,9 @@ fn fold_item(&mut self, item: clean::Item) -> Option { } else { false }; match item.inner { clean::StructItem(*) | clean::EnumItem(*) | - clean::TypedefItem(*) | clean::TraitItem(*) => { + clean::TypedefItem(*) | clean::TraitItem(*) | + clean::FunctionItem(*) | clean::ModuleItem(*) | + clean::VariantItem(*) => { self.paths.insert(item.id, (self.stack.clone(), shortty(&item))); } _ => {} @@ -479,6 +481,8 @@ fn render(w: io::file::FileWriter, cx: &mut Context, it: &clean::Item, } match item.inner { + // modules are special because they add a namespace. We also need to + // recurse into the items of the module as well. clean::ModuleItem(*) => { let name = item.name.get_ref().to_owned(); let item = Cell::new(item); @@ -498,11 +502,29 @@ fn render(w: io::file::FileWriter, cx: &mut Context, it: &clean::Item, } } } + + // Things which don't have names (like impls) don't get special + // pages dedicated to them. _ if item.name.is_some() => { let dst = self.dst.push(item_path(&item)); let writer = dst.open_writer(io::CreateOrTruncate); render(writer.unwrap(), self, &item, true); + + // recurse if necessary + let name = item.name.get_ref().clone(); + match item.inner { + clean::EnumItem(e) => { + let mut it = e.variants.move_iter(); + do self.recurse(name) |this| { + for item in it { + f(this, item); + } + } + } + _ => {} + } } + _ => {} } } @@ -696,17 +718,43 @@ fn fmt(s: &Initializer<'self>, f: &mut fmt::Formatter) { write!(w, " - {}: {} = {} + {}static {}: {} = {} {}  ", + VisSpace(myitem.visibility), *myitem.name.get_ref(), s.type_, Initializer(s.expr), Markdown(blank(myitem.doc_value()))); } + clean::ViewItemItem(ref item) => { + match item.inner { + clean::ExternMod(ref name, ref src, _, _) => { + write!(w, "extern mod {}", + name.as_slice()); + match *src { + Some(ref src) => write!(w, " = \"{}\"", + src.as_slice()), + None => {} + } + write!(w, ";"); + } + + clean::Import(ref imports) => { + for import in imports.iter() { + write!(w, "{}{}", + VisSpace(myitem.visibility), + *import); + } + } + } + + } + _ => { + if myitem.name.is_none() { loop } write!(w, "