1
Fork 0

rustdoc: Hyperlink cross-crate reexports

This should improve the libcore experience quite a bit when looking at the
libstd documentation.
This commit is contained in:
Alex Crichton 2014-05-09 13:52:17 -07:00
parent aa6725407a
commit 1ba4971ab8
6 changed files with 142 additions and 126 deletions

View file

@ -670,15 +670,7 @@ pub enum Type {
ResolvedPath { ResolvedPath {
pub path: Path, pub path: Path,
pub typarams: Option<Vec<TyParamBound>>, pub typarams: Option<Vec<TyParamBound>>,
pub id: ast::NodeId, pub did: ast::DefId,
},
/// Same as above, but only external variants
ExternalPath {
pub path: Path,
pub typarams: Option<Vec<TyParamBound>>,
pub fqn: Vec<~str>,
pub kind: TypeKind,
pub krate: ast::CrateNum,
}, },
// I have no idea how to usefully use this. // I have no idea how to usefully use this.
TyParamBinder(ast::NodeId), TyParamBinder(ast::NodeId),
@ -715,19 +707,18 @@ pub enum Type {
#[deriving(Clone, Encodable, Decodable)] #[deriving(Clone, Encodable, Decodable)]
pub enum TypeKind { pub enum TypeKind {
TypeStruct,
TypeEnum, TypeEnum,
TypeTrait,
TypeFunction, TypeFunction,
TypeModule,
TypeStatic,
TypeStruct,
TypeTrait,
TypeVariant,
} }
impl Clean<Type> for ast::Ty { impl Clean<Type> for ast::Ty {
fn clean(&self) -> Type { fn clean(&self) -> Type {
use syntax::ast::*; use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
let ctxt = super::ctxtkey.get().unwrap();
let codemap = ctxt.sess().codemap();
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node { match self.node {
TyNil => Unit, TyNil => Unit,
TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()), TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
@ -1153,7 +1144,7 @@ pub enum ViewPath {
// use source::*; // use source::*;
GlobImport(ImportSource), GlobImport(ImportSource),
// use source::{a, b, c}; // use source::{a, b, c};
ImportList(ImportSource, Vec<ViewListIdent> ), ImportList(ImportSource, Vec<ViewListIdent>),
} }
#[deriving(Clone, Encodable, Decodable)] #[deriving(Clone, Encodable, Decodable)]
@ -1298,48 +1289,47 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
core::NotTyped(_) => return Bool core::NotTyped(_) => return Bool
}; };
debug!("searching for {:?} in defmap", id); debug!("searching for {:?} in defmap", id);
let d = match tycx.def_map.borrow().find(&id) { let def = match tycx.def_map.borrow().find(&id) {
Some(&k) => k, Some(&k) => k,
None => { None => fail!("unresolved id not in defmap")
debug!("could not find {:?} in defmap (`{}`)", id, tycx.map.node_to_str(id));
fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
}
}; };
let (def_id, kind) = match d { match def {
ast::DefFn(i, _) => (i, TypeFunction),
ast::DefSelfTy(i) => return Self(i), ast::DefSelfTy(i) => return Self(i),
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => {
debug!("saw DefTrait in def_to_id");
(i, TypeTrait)
},
ast::DefPrimTy(p) => match p { ast::DefPrimTy(p) => match p {
ast::TyStr => return String, ast::TyStr => return String,
ast::TyBool => return Bool, ast::TyBool => return Bool,
_ => return Primitive(p) _ => return Primitive(p)
}, },
ast::DefTyParam(i, _) => return Generic(i.node), ast::DefTyParam(i, _) => return Generic(i.node),
ast::DefStruct(i) => (i, TypeStruct), ast::DefTyParamBinder(i) => return TyParamBinder(i),
ast::DefTyParamBinder(i) => { _ => {}
debug!("found a typaram_binder, what is it? {}", i);
return TyParamBinder(i);
},
x => fail!("resolved type maps to a weird def {:?}", x),
}; };
if ast_util::is_local(def_id) { let did = register_def(&**cx, def);
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node } ResolvedPath { path: path, typarams: tpbs, did: did }
} else { }
let fqn = csearch::get_item_path(tycx, def_id);
let fqn = fqn.move_iter().map(|i| i.to_str()).collect(); fn register_def(cx: &core::DocContext, def: ast::Def) -> ast::DefId {
ExternalPath { let (did, kind) = match def {
path: path, ast::DefFn(i, _) => (i, TypeFunction),
typarams: tpbs, ast::DefTy(i) => (i, TypeEnum),
fqn: fqn, ast::DefTrait(i) => (i, TypeTrait),
kind: kind, ast::DefStruct(i) => (i, TypeStruct),
krate: def_id.krate, ast::DefMod(i) => (i, TypeModule),
} ast::DefStatic(i, _) => (i, TypeStatic),
} ast::DefVariant(i, _, _) => (i, TypeEnum),
_ => return ast_util::def_id_of_def(def),
};
if ast_util::is_local(did) { return did }
let tcx = match cx.maybe_typed {
core::Typed(ref t) => t,
core::NotTyped(_) => return did
};
let fqn = csearch::get_item_path(tcx, did);
let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
debug!("recording {} => {}", did, fqn);
cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
return did;
} }
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource { fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
@ -1353,7 +1343,7 @@ fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
let cx = super::ctxtkey.get().unwrap(); let cx = super::ctxtkey.get().unwrap();
match cx.maybe_typed { match cx.maybe_typed {
core::Typed(ref tcx) => { core::Typed(ref tcx) => {
tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d)) tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
} }
core::NotTyped(_) => None core::NotTyped(_) => None
} }

View file

@ -20,7 +20,7 @@ use syntax;
use std::cell::RefCell; use std::cell::RefCell;
use std::os; use std::os;
use collections::HashSet; use collections::{HashSet, HashMap};
use visit_ast::RustdocVisitor; use visit_ast::RustdocVisitor;
use clean; use clean;
@ -31,10 +31,14 @@ pub enum MaybeTyped {
NotTyped(driver::session::Session) NotTyped(driver::session::Session)
} }
pub type ExternalPaths = RefCell<Option<HashMap<ast::DefId,
(Vec<~str>, clean::TypeKind)>>>;
pub struct DocContext { pub struct DocContext {
pub krate: ast::Crate, pub krate: ast::Crate,
pub maybe_typed: MaybeTyped, pub maybe_typed: MaybeTyped,
pub src: Path, pub src: Path,
pub external_paths: ExternalPaths,
} }
impl DocContext { impl DocContext {
@ -49,6 +53,7 @@ impl DocContext {
pub struct CrateAnalysis { pub struct CrateAnalysis {
pub exported_items: privacy::ExportedItems, pub exported_items: privacy::ExportedItems,
pub public_items: privacy::PublicItems, pub public_items: privacy::PublicItems,
pub external_paths: ExternalPaths,
} }
/// Parses, resolves, and typechecks the given crate /// Parses, resolves, and typechecks the given crate
@ -98,9 +103,11 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
krate: krate, krate: krate,
maybe_typed: Typed(ty_cx), maybe_typed: Typed(ty_cx),
src: cpath.clone(), src: cpath.clone(),
external_paths: RefCell::new(Some(HashMap::new())),
}, CrateAnalysis { }, CrateAnalysis {
exported_items: exported_items, exported_items: exported_items,
public_items: public_items, public_items: public_items,
external_paths: RefCell::new(None),
}) })
} }
@ -116,5 +123,7 @@ pub fn run_core(libs: HashSet<Path>, cfgs: Vec<~str>, path: &Path)
v.clean() v.clean()
}; };
let external_paths = ctxt.external_paths.borrow_mut().take();
*analysis.external_paths.borrow_mut() = external_paths;
(krate, analysis) (krate, analysis)
} }

View file

@ -146,41 +146,28 @@ impl fmt::Show for clean::Path {
/// Used when rendering a `ResolvedPath` structure. This invokes the `path` /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path. /// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path, fn resolved_path(w: &mut io::Writer, did: ast::DefId, p: &clean::Path,
print_all: bool) -> fmt::Result { print_all: bool) -> fmt::Result {
path(w, p, print_all, path(w, p, print_all,
|_cache, loc| { Some("../".repeat(loc.len())) }, |cache, loc| {
if ast_util::is_local(did) {
Some("../".repeat(loc.len()))
} else {
match *cache.extern_locations.get(&did.krate) {
render::Remote(ref s) => Some(s.clone()),
render::Local => Some("../".repeat(loc.len())),
render::Unknown => None,
}
}
},
|cache| { |cache| {
match cache.paths.find(&id) { match cache.paths.find(&did) {
None => None, None => None,
Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty)) Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty))
} }
}) })
} }
/// Used when rendering an `ExternalPath` structure. Like `resolved_path` this
/// will invoke `path` with proper linking-style arguments.
fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool,
fqn: &[~str], kind: clean::TypeKind,
krate: ast::CrateNum) -> fmt::Result {
path(w, p, print_all,
|cache, loc| {
match *cache.extern_locations.get(&krate) {
render::Remote(ref s) => Some(s.clone()),
render::Local => Some("../".repeat(loc.len())),
render::Unknown => None,
}
},
|_cache| {
Some((Vec::from_slice(fqn), match kind {
clean::TypeStruct => item_type::Struct,
clean::TypeEnum => item_type::Enum,
clean::TypeFunction => item_type::Function,
clean::TypeTrait => item_type::Trait,
}))
})
}
fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool, fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
root: |&render::Cache, &[~str]| -> Option<~str>, root: |&render::Cache, &[~str]| -> Option<~str>,
info: |&render::Cache| -> Option<(Vec<~str> , ItemType)>) info: |&render::Cache| -> Option<(Vec<~str> , ItemType)>)
@ -298,15 +285,9 @@ impl fmt::Show for clean::Type {
let m = cache_key.get().unwrap(); let m = cache_key.get().unwrap();
f.buf.write(m.typarams.get(&id).as_bytes()) f.buf.write(m.typarams.get(&id).as_bytes())
} }
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => { clean::ResolvedPath{ did, ref typarams, ref path} => {
try!(resolved_path(f.buf, id, path, false)); try!(resolved_path(f.buf, did, path, false));
tybounds(f.buf, tp) tybounds(f.buf, typarams)
}
clean::ExternalPath{path: ref path, typarams: ref tp,
fqn: ref fqn, kind, krate} => {
try!(external_path(f.buf, path, false, fqn.as_slice(), kind,
krate))
tybounds(f.buf, tp)
} }
clean::Self(..) => f.buf.write("Self".as_bytes()), clean::Self(..) => f.buf.write("Self".as_bytes()),
clean::Primitive(prim) => { clean::Primitive(prim) => {
@ -543,10 +524,7 @@ impl fmt::Show for clean::ViewPath {
impl fmt::Show for clean::ImportSource { impl fmt::Show for clean::ImportSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.did { match self.did {
// FIXME: shouldn't be restricted to just local imports Some(did) => resolved_path(f.buf, did, &self.path, true),
Some(did) if ast_util::is_local(did) => {
resolved_path(f.buf, did.node, &self.path, true)
}
_ => { _ => {
for (i, seg) in self.path.segments.iter().enumerate() { for (i, seg) in self.path.segments.iter().enumerate() {
if i > 0 { if i > 0 {
@ -563,8 +541,7 @@ impl fmt::Show for clean::ImportSource {
impl fmt::Show for clean::ViewListIdent { impl fmt::Show for clean::ViewListIdent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.source { match self.source {
// FIXME: shouldn't be limited to just local imports Some(did) => {
Some(did) if ast_util::is_local(did) => {
let path = clean::Path { let path = clean::Path {
global: false, global: false,
segments: vec!(clean::PathSegment { segments: vec!(clean::PathSegment {
@ -573,7 +550,7 @@ impl fmt::Show for clean::ViewListIdent {
types: Vec::new(), types: Vec::new(),
}) })
}; };
resolved_path(f.buf, did.node, &path, false) resolved_path(f.buf, did, &path, false)
} }
_ => write!(f.buf, "{}", self.name), _ => write!(f.buf, "{}", self.name),
} }

View file

@ -43,6 +43,7 @@ use std::strbuf::StrBuf;
use sync::Arc; use sync::Arc;
use serialize::json::ToJson; use serialize::json::ToJson;
use syntax::ast; use syntax::ast;
use syntax::ast_util;
use syntax::attr; use syntax::attr;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use rustc::util::nodemap::NodeSet; use rustc::util::nodemap::NodeSet;
@ -50,13 +51,13 @@ use rustc::util::nodemap::NodeSet;
use clean; use clean;
use doctree; use doctree;
use fold::DocFolder; use fold::DocFolder;
use html::item_type;
use html::item_type::{ItemType, shortty};
use html::format::{VisSpace, Method, FnStyleSpace}; use html::format::{VisSpace, Method, FnStyleSpace};
use html::layout;
use html::markdown;
use html::markdown::Markdown;
use html::highlight; use html::highlight;
use html::item_type::{ItemType, shortty};
use html::item_type;
use html::layout;
use html::markdown::Markdown;
use html::markdown;
/// Major driving force in all rustdoc rendering. This contains information /// Major driving force in all rustdoc rendering. This contains information
/// about where in the tree-like hierarchy rendering is occurring and controls /// about where in the tree-like hierarchy rendering is occurring and controls
@ -138,7 +139,7 @@ pub struct Cache {
/// URLs when a type is being linked to. External paths are not located in /// URLs when a type is being linked to. External paths are not located in
/// this map because the `External` type itself has all the information /// this map because the `External` type itself has all the information
/// necessary. /// necessary.
pub paths: HashMap<ast::NodeId, (Vec<~str> , ItemType)>, pub paths: HashMap<ast::DefId, (Vec<~str>, ItemType)>,
/// This map contains information about all known traits of this crate. /// This map contains information about all known traits of this crate.
/// Implementations of a crate should inherit the documentation of the /// Implementations of a crate should inherit the documentation of the
@ -242,12 +243,26 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
} }
// Crawl the crate to build various caches used for the output // Crawl the crate to build various caches used for the output
let public_items = ::analysiskey.get().map(|a| a.public_items.clone()); let analysis = ::analysiskey.get();
let public_items = public_items.unwrap_or(NodeSet::new()); let public_items = analysis.as_ref().map(|a| a.public_items.clone());
let paths = analysis.as_ref().map(|a| {
let paths = a.external_paths.borrow_mut().take_unwrap();
paths.move_iter().map(|(k, (v, t))| {
(k, (v, match t {
clean::TypeStruct => item_type::Struct,
clean::TypeEnum => item_type::Enum,
clean::TypeFunction => item_type::Function,
clean::TypeTrait => item_type::Trait,
clean::TypeModule => item_type::Module,
clean::TypeStatic => item_type::Static,
clean::TypeVariant => item_type::Variant,
}))
}).collect()
}).unwrap_or(HashMap::new());
let mut cache = Cache { let mut cache = Cache {
impls: HashMap::new(), impls: HashMap::new(),
typarams: HashMap::new(), typarams: HashMap::new(),
paths: HashMap::new(), paths: paths,
traits: HashMap::new(), traits: HashMap::new(),
implementors: HashMap::new(), implementors: HashMap::new(),
stack: Vec::new(), stack: Vec::new(),
@ -255,7 +270,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
search_index: Vec::new(), search_index: Vec::new(),
extern_locations: HashMap::new(), extern_locations: HashMap::new(),
privmod: false, privmod: false,
public_items: public_items, public_items: public_items.unwrap_or(NodeSet::new()),
orphan_methods: Vec::new(), orphan_methods: Vec::new(),
}; };
cache.stack.push(krate.name.clone()); cache.stack.push(krate.name.clone());
@ -269,15 +284,16 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
// Attach all orphan methods to the type's definition if the type // Attach all orphan methods to the type's definition if the type
// has since been learned. // has since been learned.
for &(ref pid, ref item) in meths.iter() { for &(pid, ref item) in meths.iter() {
match paths.find(pid) { let did = ast_util::local_def(pid);
match paths.find(&did) {
Some(&(ref fqp, _)) => { Some(&(ref fqp, _)) => {
index.push(IndexItem { index.push(IndexItem {
ty: shortty(item), ty: shortty(item),
name: item.name.clone().unwrap(), name: item.name.clone().unwrap(),
path: fqp.slice_to(fqp.len() - 1).connect("::"), path: fqp.slice_to(fqp.len() - 1).connect("::"),
desc: shorter(item.doc_value()).to_owned(), desc: shorter(item.doc_value()).to_owned(),
parent: Some(*pid), parent: Some(pid),
}); });
}, },
None => {} None => {}
@ -336,7 +352,8 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
try!(write!(&mut w, r#"],"paths":["#)); try!(write!(&mut w, r#"],"paths":["#));
for (i, &nodeid) in pathid_to_nodeid.iter().enumerate() { for (i, &nodeid) in pathid_to_nodeid.iter().enumerate() {
let &(ref fqp, short) = cache.paths.find(&nodeid).unwrap(); let def = ast_util::local_def(nodeid);
let &(ref fqp, short) = cache.paths.find(&def).unwrap();
if i > 0 { if i > 0 {
try!(write!(&mut w, ",")); try!(write!(&mut w, ","));
} }
@ -414,6 +431,8 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
for &(n, ref e) in krate.externs.iter() { for &(n, ref e) in krate.externs.iter() {
cache.extern_locations.insert(n, extern_location(e, &cx.dst)); cache.extern_locations.insert(n, extern_location(e, &cx.dst));
let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID };
cache.paths.insert(did, (Vec::new(), item_type::Module));
} }
// And finally render the whole crate's documentation // And finally render the whole crate's documentation
@ -605,7 +624,12 @@ impl DocFolder for Cache {
match item.inner { match item.inner {
clean::ImplItem(ref i) => { clean::ImplItem(ref i) => {
match i.trait_ { match i.trait_ {
Some(clean::ResolvedPath{ id, .. }) => { // FIXME: this is_local() check seems to be losing
// information
Some(clean::ResolvedPath{ did, .. })
if ast_util::is_local(did) =>
{
let id = did.node;
let v = self.implementors.find_or_insert_with(id, |_|{ let v = self.implementors.find_or_insert_with(id, |_|{
Vec::new() Vec::new()
}); });
@ -642,7 +666,8 @@ impl DocFolder for Cache {
(None, None) (None, None)
} else { } else {
let last = self.parent_stack.last().unwrap(); let last = self.parent_stack.last().unwrap();
let path = match self.paths.find(last) { let did = ast_util::local_def(*last);
let path = match self.paths.find(&did) {
Some(&(_, item_type::Trait)) => Some(&(_, item_type::Trait)) =>
Some(self.stack.slice_to(self.stack.len() - 1)), Some(self.stack.slice_to(self.stack.len() - 1)),
// The current stack not necessarily has correlation for // The current stack not necessarily has correlation for
@ -698,10 +723,11 @@ impl DocFolder for Cache {
// a reexported item doesn't show up in the `public_items` map, // a reexported item doesn't show up in the `public_items` map,
// so we can skip inserting into the paths map if there was // so we can skip inserting into the paths map if there was
// already an entry present and we're not a public item. // already an entry present and we're not a public item.
if !self.paths.contains_key(&item.id) || let did = ast_util::local_def(item.id);
if !self.paths.contains_key(&did) ||
self.public_items.contains(&item.id) { self.public_items.contains(&item.id) {
self.paths.insert(item.id, self.paths.insert(did, (self.stack.clone(),
(self.stack.clone(), shortty(&item))); shortty(&item)));
} }
} }
// link variants to their parent enum because pages aren't emitted // link variants to their parent enum because pages aren't emitted
@ -709,7 +735,8 @@ impl DocFolder for Cache {
clean::VariantItem(..) => { clean::VariantItem(..) => {
let mut stack = self.stack.clone(); let mut stack = self.stack.clone();
stack.pop(); stack.pop();
self.paths.insert(item.id, (stack, item_type::Enum)); self.paths.insert(ast_util::local_def(item.id),
(stack, item_type::Enum));
} }
_ => {} _ => {}
} }
@ -721,8 +748,13 @@ impl DocFolder for Cache {
} }
clean::ImplItem(ref i) => { clean::ImplItem(ref i) => {
match i.for_ { match i.for_ {
clean::ResolvedPath{ id, .. } => { clean::ResolvedPath{ did, .. } => {
self.parent_stack.push(id); true if ast_util::is_local(did) {
self.parent_stack.push(did.node);
true
} else {
false
}
} }
_ => false _ => false
} }
@ -737,8 +769,10 @@ impl DocFolder for Cache {
match item { match item {
clean::Item{ attrs, inner: clean::ImplItem(i), .. } => { clean::Item{ attrs, inner: clean::ImplItem(i), .. } => {
match i.for_ { match i.for_ {
clean::ResolvedPath { id, .. } => { clean::ResolvedPath { did, .. }
let v = self.impls.find_or_insert_with(id, |_| { if ast_util::is_local(did) =>
{
let v = self.impls.find_or_insert_with(did.node, |_| {
Vec::new() Vec::new()
}); });
// extract relevant documentation for this impl // extract relevant documentation for this impl
@ -1595,7 +1629,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
Some(ref ty) => { Some(ref ty) => {
try!(write!(w, "{} for ", *ty)); try!(write!(w, "{} for ", *ty));
match *ty { match *ty {
clean::ResolvedPath { id, .. } => Some(id), clean::ResolvedPath { did, .. } => Some(did),
_ => None, _ => None,
} }
} }
@ -1634,9 +1668,10 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
// default methods which weren't overridden in the implementation block. // default methods which weren't overridden in the implementation block.
match trait_id { match trait_id {
None => {} None => {}
Some(id) => { // FIXME: this should work for non-local traits
Some(did) if ast_util::is_local(did) => {
try!({ try!({
match cache_key.get().unwrap().traits.find(&id) { match cache_key.get().unwrap().traits.find(&did.node) {
Some(t) => { Some(t) => {
for method in t.methods.iter() { for method in t.methods.iter() {
let n = method.item().name.clone(); let n = method.item().name.clone();
@ -1653,6 +1688,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
Ok(()) Ok(())
}) })
} }
Some(..) => {}
} }
try!(write!(w, "</div>")); try!(write!(w, "</div>"));
Ok(()) Ok(())

View file

@ -65,9 +65,10 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
impl<'a> fold::DocFolder for ImplStripper<'a> { impl<'a> fold::DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> { fn fold_item(&mut self, i: Item) -> Option<Item> {
match i.inner { match i.inner {
clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: for_id, .. }, clean::ImplItem(clean::Impl{
.. }) => { for_: clean::ResolvedPath{ did, .. }, ..
if self.stripped.contains(&for_id) { }) => {
if self.stripped.contains(&did.node) {
return None; return None;
} }
} }
@ -146,8 +147,10 @@ impl<'a> fold::DocFolder for Stripper<'a> {
clean::ModuleItem(..) => {} clean::ModuleItem(..) => {}
// trait impls for private items should be stripped // trait impls for private items should be stripped
clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: ref for_id, .. }, .. }) => { clean::ImplItem(clean::Impl{
if !self.exported_items.contains(for_id) { for_: clean::ResolvedPath{ did, .. }, ..
}) => {
if !self.exported_items.contains(&did.node) {
return None; return None;
} }
} }
@ -201,9 +204,9 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
match i.inner { match i.inner {
clean::ImplItem(ref imp) => { clean::ImplItem(ref imp) => {
match imp.trait_ { match imp.trait_ {
Some(clean::ResolvedPath{ id, .. }) => { Some(clean::ResolvedPath{ did, .. }) => {
let ImplStripper(s) = *self; let ImplStripper(s) = *self;
if !s.contains(&id) { if !s.contains(&did.node) {
return None; return None;
} }
} }

View file

@ -16,7 +16,7 @@ use std::os;
use std::str; use std::str;
use std::strbuf::StrBuf; use std::strbuf::StrBuf;
use collections::HashSet; use collections::{HashSet, HashMap};
use testing; use testing;
use rustc::back::link; use rustc::back::link;
use rustc::driver::driver; use rustc::driver::driver;
@ -73,6 +73,7 @@ pub fn run(input: &str,
krate: krate, krate: krate,
maybe_typed: core::NotTyped(sess), maybe_typed: core::NotTyped(sess),
src: input_path, src: input_path,
external_paths: RefCell::new(Some(HashMap::new())),
}; };
super::ctxtkey.replace(Some(ctx)); super::ctxtkey.replace(Some(ctx));