From 900191891fc5462d4ef33756a7d4d40e78e1c1cc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Nov 2016 08:15:16 +0200 Subject: [PATCH] rustdoc: link to cross-crate sources directly. --- src/librustdoc/clean/inline.rs | 10 +- src/librustdoc/clean/mod.rs | 175 ++++++++++++------------- src/librustdoc/core.rs | 2 - src/librustdoc/html/format.rs | 22 ++-- src/librustdoc/html/render.rs | 166 ++++++++++------------- src/librustdoc/html/static/main.js | 9 -- src/test/rustdoc/issue-34274.rs | 2 +- src/test/rustdoc/src-links-external.rs | 5 +- 8 files changed, 173 insertions(+), 218 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e3274611e5bff..bf739abe3da0d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -115,7 +115,7 @@ fn try_inline_def(cx: &DocContext, def: Def) -> Option> { let did = def.def_id(); cx.renderinfo.borrow_mut().inlined.insert(did); ret.push(clean::Item { - source: clean::Span::empty(), + source: tcx.def_span(did).clean(cx), name: Some(tcx.item_name(did).to_string()), attrs: load_attrs(cx, did), inner: inner, @@ -321,7 +321,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { clean::RegionBound(..) => unreachable!(), }, }), - source: clean::Span::empty(), + source: tcx.def_span(did).clean(cx), name: None, attrs: attrs, visibility: Some(clean::Inherited), @@ -357,7 +357,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { tcx.item_type(item.def_id).clean(cx), default, ), - source: clean::Span::empty(), + source: tcx.def_span(item.def_id).clean(cx), attrs: clean::Attributes::default(), visibility: None, stability: tcx.lookup_stability(item.def_id).clean(cx), @@ -404,7 +404,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { Some(clean::Item { name: Some(item.name.clean(cx)), inner: clean::TypedefItem(typedef, true), - source: clean::Span::empty(), + source: tcx.def_span(item.def_id).clean(cx), attrs: clean::Attributes::default(), visibility: None, stability: tcx.lookup_stability(item.def_id).clean(cx), @@ -442,7 +442,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { items: trait_items, polarity: Some(polarity.clean(cx)), }), - source: clean::Span::empty(), + source: tcx.def_span(did).clean(cx), name: None, attrs: attrs, visibility: Some(clean::Inherited), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e233613ee629e..dba613ed1b6b3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -27,11 +27,10 @@ use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::{self, DUMMY_SP, Pos}; -use rustc_trans::back::link; use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::hir::def::{Def, CtorKind}; -use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::print as pprust; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind}; @@ -45,7 +44,6 @@ use std::rc::Rc; use std::slice; use std::sync::Arc; use std::u32; -use std::env::current_dir; use std::mem; use core::DocContext; @@ -110,19 +108,16 @@ pub struct Crate { pub name: String, pub src: PathBuf, pub module: Option, - pub externs: Vec<(def_id::CrateNum, ExternalCrate)>, - pub primitives: Vec, + pub externs: Vec<(CrateNum, ExternalCrate)>, + pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, pub access_levels: Arc>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. pub external_traits: FxHashMap, } -struct CrateNum(def_id::CrateNum); - impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { fn clean(&self, cx: &DocContext) -> Crate { - use rustc::session::config::Input; use ::visit_lib::LibEmbargoVisitor; { @@ -133,83 +128,41 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { let mut externs = Vec::new(); for cnum in cx.sess().cstore.crates() { - externs.push((cnum, CrateNum(cnum).clean(cx))); + externs.push((cnum, cnum.clean(cx))); // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); } externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - // Figure out the name of this crate - let input = &cx.input; - let name = link::find_crate_name(None, &self.attrs, input); - // Clean the crate, translating the entire libsyntax AST to one that is // understood by rustdoc. let mut module = self.module.clean(cx); - // Collect all inner modules which are tagged as implementations of - // primitives. - // - // Note that this loop only searches the top-level items of the crate, - // and this is intentional. If we were to search the entire crate for an - // item tagged with `#[doc(primitive)]` then we would also have to - // search the entirety of external modules for items tagged - // `#[doc(primitive)]`, which is a pretty inefficient process (decoding - // all that metadata unconditionally). - // - // In order to keep the metadata load under control, the - // `#[doc(primitive)]` feature is explicitly designed to only allow the - // primitive tags to show up as the top level items in a crate. - // - // Also note that this does not attempt to deal with modules tagged - // duplicately for the same primitive. This is handled later on when - // rendering by delegating everything to a hash map. - let mut primitives = Vec::new(); + let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx); { let m = match module.inner { ModuleItem(ref mut m) => m, _ => unreachable!(), }; - let mut tmp = Vec::new(); - for child in &mut m.items { - if !child.is_mod() { - continue; - } - let prim = match PrimitiveType::find(&child.attrs) { - Some(prim) => prim, - None => continue, - }; - primitives.push(prim); - tmp.push(Item { + m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { + Item { source: Span::empty(), name: Some(prim.to_url_str().to_string()), - attrs: child.attrs.clone(), + attrs: attrs.clone(), visibility: Some(Public), stability: None, deprecation: None, - def_id: DefId::local(prim.to_def_index()), + def_id: def_id, inner: PrimitiveItem(prim), - }); - } - m.items.extend(tmp); - } - - let src = match cx.input { - Input::File(ref path) => { - if path.is_absolute() { - path.clone() - } else { - current_dir().unwrap().join(path) } - }, - Input::Str { ref name, .. } => PathBuf::from(name.clone()), - }; + })); + } let mut access_levels = cx.access_levels.borrow_mut(); let mut external_traits = cx.external_traits.borrow_mut(); Crate { - name: name.to_string(), + name: name, src: src, module: Some(module), externs: externs, @@ -223,21 +176,78 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ExternalCrate { pub name: String, + pub src: PathBuf, pub attrs: Attributes, - pub primitives: Vec, + pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, } impl Clean for CrateNum { fn clean(&self, cx: &DocContext) -> ExternalCrate { - let mut primitives = Vec::new(); - let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; - for item in cx.tcx.sess.cstore.item_children(root) { - let attrs = inline::load_attrs(cx, item.def.def_id()); - PrimitiveType::find(&attrs).map(|prim| primitives.push(prim)); - } + let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; + let krate_span = cx.tcx.def_span(root); + let krate_src = cx.sess().codemap().span_to_filename(krate_span); + + // Collect all inner modules which are tagged as implementations of + // primitives. + // + // Note that this loop only searches the top-level items of the crate, + // and this is intentional. If we were to search the entire crate for an + // item tagged with `#[doc(primitive)]` then we would also have to + // search the entirety of external modules for items tagged + // `#[doc(primitive)]`, which is a pretty inefficient process (decoding + // all that metadata unconditionally). + // + // In order to keep the metadata load under control, the + // `#[doc(primitive)]` feature is explicitly designed to only allow the + // primitive tags to show up as the top level items in a crate. + // + // Also note that this does not attempt to deal with modules tagged + // duplicately for the same primitive. This is handled later on when + // rendering by delegating everything to a hash map. + let as_primitive = |def: Def| { + if let Def::Mod(def_id) = def { + let attrs = cx.tcx.get_attrs(def_id).clean(cx); + let mut prim = None; + for attr in attrs.lists("doc") { + if let Some(v) = attr.value_str() { + if attr.check_name("primitive") { + prim = PrimitiveType::from_str(&v.as_str()); + if prim.is_some() { + break; + } + } + } + } + return prim.map(|p| (def_id, p, attrs)); + } + None + }; + let primitives = if root.is_local() { + cx.tcx.map.krate().module.item_ids.iter().filter_map(|&id| { + let item = cx.tcx.map.expect_item(id.id); + match item.node { + hir::ItemMod(_) => { + as_primitive(Def::Mod(cx.tcx.map.local_def_id(id.id))) + } + hir::ItemUse(ref path, hir::UseKind::Single) + if item.vis == hir::Visibility::Public => { + as_primitive(path.def).map(|(_, prim, attrs)| { + // Pretend the primitive is local. + (cx.tcx.map.local_def_id(id.id), prim, attrs) + }) + } + _ => None + } + }).collect() + } else { + cx.tcx.sess.cstore.item_children(root).iter().map(|item| item.def) + .filter_map(as_primitive).collect() + }; + ExternalCrate { - name: cx.sess().cstore.crate_name(self.0).to_string(), - attrs: cx.sess().cstore.item_attrs(root).clean(cx), + name: cx.tcx.crate_name(*self).to_string(), + src: PathBuf::from(krate_src), + attrs: cx.tcx.get_attrs(root).clean(cx), primitives: primitives, } } @@ -1460,7 +1470,7 @@ impl<'tcx> Clean for ty::AssociatedItem { deprecation: get_deprecation(cx, self.def_id), def_id: self.def_id, attrs: inline::load_attrs(cx, self.def_id), - source: Span::empty(), + source: cx.tcx.def_span(self.def_id).clean(cx), inner: inner, } } @@ -1618,19 +1628,6 @@ impl PrimitiveType { } } - fn find(attrs: &Attributes) -> Option { - for attr in attrs.lists("doc") { - if let Some(v) = attr.value_str() { - if attr.check_name("primitive") { - if let ret@Some(..) = PrimitiveType::from_str(&v.as_str()) { - return ret; - } - } - } - } - None - } - pub fn as_str(&self) -> &'static str { match *self { PrimitiveType::Isize => "isize", @@ -1658,14 +1655,6 @@ impl PrimitiveType { pub fn to_url_str(&self) -> &'static str { self.as_str() } - - /// Creates a rustdoc-specific node id for primitive types. - /// - /// These node ids are generally never used by the AST itself. - pub fn to_def_index(&self) -> DefIndex { - let x = u32::MAX - 1 - (*self as u32); - DefIndex::new(x as usize) - } } impl From for PrimitiveType { @@ -1948,7 +1937,7 @@ impl<'tcx> Clean for ty::FieldDefData<'tcx, 'static> { Item { name: Some(self.name).clean(cx), attrs: cx.tcx.get_attrs(self.did).clean(cx), - source: Span::empty(), + source: cx.tcx.def_span(self.did).clean(cx), visibility: self.vis.clean(cx), stability: get_stability(cx, self.did), deprecation: get_deprecation(cx, self.did), @@ -2115,7 +2104,7 @@ impl<'tcx> Clean for ty::VariantDefData<'tcx, 'static> { fields_stripped: false, fields: self.fields.iter().map(|field| { Item { - source: Span::empty(), + source: cx.tcx.def_span(field.did).clean(cx), name: Some(field.name.clean(cx)), attrs: cx.tcx.get_attrs(field.did).clean(cx), visibility: field.vis.clean(cx), @@ -2131,7 +2120,7 @@ impl<'tcx> Clean for ty::VariantDefData<'tcx, 'static> { Item { name: Some(self.name.clean(cx)), attrs: inline::load_attrs(cx, self.did), - source: Span::empty(), + source: cx.tcx.def_span(self.did).clean(cx), visibility: Some(Inherited), def_id: self.did, inner: VariantItem(Variant { kind: kind }), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4c2487e2b42a0..df25473ddd916 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -45,7 +45,6 @@ pub type ExternalPaths = FxHashMap, clean::TypeKind)>; pub struct DocContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub input: Input, pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -187,7 +186,6 @@ pub fn run_core(search_paths: SearchPaths, let ctxt = DocContext { tcx: tcx, - input: input, populated_all_crate_impls: Cell::new(false), access_levels: RefCell::new(access_levels), external_traits: Default::default(), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index aed41916f5c53..6dc6e80dae0b8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,7 +18,7 @@ use std::fmt; use std::iter::repeat; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def_id::DefId; use syntax::abi::Abi; use rustc::hir; @@ -403,9 +403,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { None => match cache.external_paths.get(&did) { Some(&(ref fqp, shortty)) => { (fqp, shortty, match cache.extern_locations[&did.krate] { - (_, render::Remote(ref s)) => s.to_string(), - (_, render::Local) => repeat("../").take(loc.len()).collect(), - (_, render::Unknown) => return None, + (.., render::Remote(ref s)) => s.to_string(), + (.., render::Local) => repeat("../").take(loc.len()).collect(), + (.., render::Unknown) => return None, }) } None => return None, @@ -479,7 +479,7 @@ fn primitive_link(f: &mut fmt::Formatter, let mut needs_termination = false; if !f.alternate() { match m.primitive_locations.get(&prim) { - Some(&LOCAL_CRATE) => { + Some(&def_id) if def_id.is_local() => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); let len = if len == 0 {0} else {len - 1}; write!(f, "", @@ -487,14 +487,16 @@ fn primitive_link(f: &mut fmt::Formatter, prim.to_url_str())?; needs_termination = true; } - Some(&cnum) => { - let loc = match m.extern_locations[&cnum] { - (ref cname, render::Remote(ref s)) => Some((cname, s.to_string())), - (ref cname, render::Local) => { + Some(&def_id) => { + let loc = match m.extern_locations[&def_id.krate] { + (ref cname, _, render::Remote(ref s)) => { + Some((cname, s.to_string())) + } + (ref cname, _, render::Local) => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); Some((cname, repeat("../").take(len).collect::())) } - (_, render::Unknown) => None, + (.., render::Unknown) => None, }; if let Some((cname, root)) = loc { write!(f, "", diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 757db81c44021..cbf93662811da 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -55,7 +55,7 @@ use externalfiles::ExternalHtml; use serialize::json::{ToJson, Json, as_json}; use syntax::{abi, ast}; use syntax::feature_gate::UnstableFeatures; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::hir; @@ -241,10 +241,10 @@ pub struct Cache { pub implementors: FxHashMap>, /// Cache of where external crate documentation can be found. - pub extern_locations: FxHashMap, + pub extern_locations: FxHashMap, /// Cache of where documentation for primitives can be found. - pub primitive_locations: FxHashMap, + pub primitive_locations: FxHashMap, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -523,8 +523,13 @@ pub fn run(mut krate: clean::Crate, // Cache where all our extern crates are located for &(n, ref e) in &krate.externs { - cache.extern_locations.insert(n, (e.name.clone(), + let src_root = match Path::new(&e.src).parent() { + Some(p) => p.to_path_buf(), + None => PathBuf::new(), + }; + cache.extern_locations.insert(n, (e.name.clone(), src_root, extern_location(e, &cx.dst))); + let did = DefId { krate: n, index: CRATE_DEF_INDEX }; cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); } @@ -533,13 +538,13 @@ pub fn run(mut krate: clean::Crate, // // Favor linking to as local extern as possible, so iterate all crates in // reverse topological order. - for &(n, ref e) in krate.externs.iter().rev() { - for &prim in &e.primitives { - cache.primitive_locations.insert(prim, n); + for &(_, ref e) in krate.externs.iter().rev() { + for &(def_id, prim, _) in &e.primitives { + cache.primitive_locations.insert(prim, def_id); } } - for &prim in &krate.primitives { - cache.primitive_locations.insert(prim, LOCAL_CRATE); + for &(def_id, prim, _) in &krate.primitives { + cache.primitive_locations.insert(prim, def_id); } cache.stack.push(krate.name.clone()); @@ -875,6 +880,8 @@ impl<'a> DocFolder for SourceCollector<'a> { if self.scx.include_sources // skip all invalid spans && item.source.filename != "" + // skip non-local items + && item.def_id.is_local() // Macros from other libraries get special filenames which we can // safely ignore. && !(item.source.filename.starts_with("<") @@ -1127,13 +1134,15 @@ impl DocFolder for Cache { true } ref t => { - match t.primitive_type() { - Some(prim) => { - let did = DefId::local(prim.to_def_index()); + let prim_did = t.primitive_type().and_then(|t| { + self.primitive_locations.get(&t).cloned() + }); + match prim_did { + Some(did) => { self.parent_stack.push(did); true } - _ => false, + None => false, } } } @@ -1158,10 +1167,7 @@ impl DocFolder for Cache { } ref t => { t.primitive_type().and_then(|t| { - self.primitive_locations.get(&t).map(|n| { - let id = t.to_def_index(); - DefId { krate: *n, index: id } - }) + self.primitive_locations.get(&t).cloned() }) } } @@ -1439,79 +1445,50 @@ impl<'a> Item<'a> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn href(&self) -> Option { - let href = if self.item.source.loline == self.item.source.hiline { - format!("{}", self.item.source.loline) - } else { - format!("{}-{}", self.item.source.loline, self.item.source.hiline) - }; + fn src_href(&self) -> Option { + let mut root = self.cx.root_path(); - // First check to see if this is an imported macro source. In this case - // we need to handle it specially as cross-crate inlined macros have... - // odd locations! - let imported_macro_from = match self.item.inner { - clean::MacroItem(ref m) => m.imported_from.as_ref(), - _ => None, - }; - if let Some(krate) = imported_macro_from { - let cache = cache(); - let root = cache.extern_locations.values().find(|&&(ref n, _)| { - *krate == *n - }).map(|l| &l.1); - let root = match root { - Some(&Remote(ref s)) => s.to_string(), - Some(&Local) => self.cx.root_path(), - None | Some(&Unknown) => return None, - }; - Some(format!("{root}/{krate}/macro.{name}.html?gotomacrosrc=1", - root = root, - krate = krate, - name = self.item.name.as_ref().unwrap())) - - // If this item is part of the local crate, then we're guaranteed to - // know the span, so we plow forward and generate a proper url. The url - // has anchors for the line numbers that we're linking to. - } else if self.item.def_id.is_local() { + let cache = cache(); + let mut path = String::new(); + let (krate, path) = if self.item.def_id.is_local() { let path = PathBuf::from(&self.item.source.filename); - self.cx.shared.local_sources.get(&path).map(|path| { - format!("{root}src/{krate}/{path}#{href}", - root = self.cx.root_path(), - krate = self.cx.shared.layout.krate, - path = path, - href = href) - }) - // If this item is not part of the local crate, then things get a little - // trickier. We don't actually know the span of the external item, but - // we know that the documentation on the other end knows the span! - // - // In this case, we generate a link to the *documentation* for this type - // in the original crate. There's an extra URL parameter which says that - // we want to go somewhere else, and the JS on the destination page will - // pick it up and instantly redirect the browser to the source code. - // - // If we don't know where the external documentation for this crate is - // located, then we return `None`. + if let Some(path) = self.cx.shared.local_sources.get(&path) { + (&self.cx.shared.layout.krate, path) + } else { + return None; + } } else { - let cache = cache(); - let external_path = match cache.external_paths.get(&self.item.def_id) { - Some(&(ref path, _)) => path, - None => return None, - }; - let mut path = match cache.extern_locations.get(&self.item.def_id.krate) { - Some(&(_, Remote(ref s))) => s.to_string(), - Some(&(_, Local)) => self.cx.root_path(), - Some(&(_, Unknown)) => return None, - None => return None, + let (krate, src_root) = match cache.extern_locations.get(&self.item.def_id.krate) { + Some(&(ref name, ref src, Local)) => (name, src), + Some(&(ref name, ref src, Remote(ref s))) => { + root = s.to_string(); + (name, src) + } + Some(&(_, _, Unknown)) | None => return None, }; - for item in &external_path[..external_path.len() - 1] { - path.push_str(item); - path.push_str("/"); - } - Some(format!("{path}{file}?gotosrc={goto}", - path = path, - file = item_path(self.item.type_(), external_path.last().unwrap()), - goto = self.item.def_id.index.as_usize())) - } + + let file = Path::new(&self.item.source.filename); + clean_srcpath(&src_root, file, false, |component| { + path.push_str(component); + path.push('/'); + }); + let mut fname = file.file_name().expect("source has no filename") + .to_os_string(); + fname.push(".html"); + path.push_str(&fname.to_string_lossy()); + (krate, &path) + }; + + let lines = if self.item.source.loline == self.item.source.hiline { + format!("{}", self.item.source.loline) + } else { + format!("{}-{}", self.item.source.loline, self.item.source.hiline) + }; + Some(format!("{root}src/{krate}/{path}#{lines}", + root = root, + krate = krate, + path = path, + lines = lines)) } } @@ -1576,10 +1553,9 @@ impl<'a> fmt::Display for Item<'a> { // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.href() { - write!(fmt, "[src]", - self.item.def_id.index.as_usize(), l, "goto source code")?; + if let Some(l) = self.src_href() { + write!(fmt, "[src]", + l, "goto source code")?; } } @@ -2781,8 +2757,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl, render_assoc_items(w, cx, container_item, did, what) } else { if let Some(prim) = target.primitive_type() { - if let Some(c) = cache().primitive_locations.get(&prim) { - let did = DefId { krate: *c, index: prim.to_def_index() }; + if let Some(&did) = cache().primitive_locations.get(&prim) { render_assoc_items(w, cx, container_item, did, what)?; } } @@ -2796,12 +2771,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "

{}", i.inner_impl())?; write!(w, "")?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); - if let Some(l) = (Item { item: &i.impl_item, cx: cx }).href() { + if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { write!(w, "
")?; render_stability_since_raw(w, since, outer_version)?; - write!(w, "[src]", - i.impl_item.def_id.index.as_usize(), l, "goto source code")?; + write!(w, "[src]", + l, "goto source code")?; } else { render_stability_since_raw(w, since, outer_version)?; } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 5ffab949d019c..6ea25fa1241f8 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -923,15 +923,6 @@ window.register_implementors(window.pending_implementors); } - // See documentation in html/render.rs for what this is doing. - var query = getQueryStringParams(); - if (query['gotosrc']) { - window.location = $('#src-' + query['gotosrc']).attr('href'); - } - if (query['gotomacrosrc']) { - window.location = $('.srclink').attr('href'); - } - function labelForToggleButton(sectionIsCollapsed) { if (sectionIsCollapsed) { // button will expand the section diff --git a/src/test/rustdoc/issue-34274.rs b/src/test/rustdoc/issue-34274.rs index 971c89b1619ed..12f880421616f 100644 --- a/src/test/rustdoc/issue-34274.rs +++ b/src/test/rustdoc/issue-34274.rs @@ -16,5 +16,5 @@ extern crate issue_34274; -// @has foo/fn.extern_c_fn.html '//a/@href' '../issue_34274/fn.extern_c_fn.html?gotosrc=' +// @has foo/fn.extern_c_fn.html '//a/@href' '../src/issue_34274/issue-34274.rs.html#12' pub use issue_34274::extern_c_fn; diff --git a/src/test/rustdoc/src-links-external.rs b/src/test/rustdoc/src-links-external.rs index e9db4f519ed97..d3307bb4d42c1 100644 --- a/src/test/rustdoc/src-links-external.rs +++ b/src/test/rustdoc/src-links-external.rs @@ -11,12 +11,13 @@ // aux-build:src-links-external.rs // build-aux-docs // ignore-cross-compile +// ignore-tidy-linelength #![crate_name = "foo"] extern crate src_links_external; -// @has foo/bar/index.html '//a/@href' '../src_links_external/index.html?gotosrc=' +// @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11' pub use src_links_external as bar; -// @has foo/bar/struct.Foo.html '//a/@href' '../src_links_external/struct.Foo.html?gotosrc=' +// @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11'