diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8b65a7d6791..263a93a9d67 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1270,6 +1270,7 @@ impl Clean for ast::ImplItem { ast::MacImplItem(_) => { MacroItem(Macro { source: self.span.to_src(cx), + imported_from: None, }) } }; @@ -2557,6 +2558,7 @@ fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Macro { pub source: String, + pub imported_from: Option, } impl Clean for doctree::Macro { @@ -2570,6 +2572,7 @@ impl Clean for doctree::Macro { def_id: ast_util::local_def(self.id), inner: MacroItem(Macro { source: self.whence.to_src(cx), + imported_from: self.imported_from.clean(cx), }), } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 862bca1b813..8fa92304d24 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -214,6 +214,7 @@ pub struct Macro { pub attrs: Vec, pub whence: Span, pub stab: Option, + pub imported_from: Option, } pub struct ExternCrate { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8b6969f586e..bb53d532f52 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -288,9 +288,9 @@ pub fn href(did: ast::DefId) -> Option<(String, ItemType, Vec)> { repeat("../").take(loc.len()).collect::() } else { 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, } }; for component in &fqp[..fqp.len() - 1] { @@ -379,12 +379,12 @@ fn primitive_link(f: &mut fmt::Formatter, node: ast::CRATE_NODE_ID, }]; let loc = match m.extern_locations[&cnum] { - render::Remote(ref s) => Some(s.to_string()), - render::Local => { + (_, render::Remote(ref s)) => Some(s.to_string()), + (_, render::Local) => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); Some(repeat("../").take(len).collect::()) } - render::Unknown => None, + (_, render::Unknown) => None, }; match loc { Some(root) => { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c619421635d..e3df0fc9ba6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -193,7 +193,7 @@ pub struct Cache { pub implementors: HashMap>, /// Cache of where external crate documentation can be found. - pub extern_locations: HashMap, + pub extern_locations: HashMap, /// Cache of where documentation for primitives can be found. pub primitive_locations: HashMap, @@ -408,7 +408,8 @@ 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, extern_location(e, &cx.dst)); + cache.extern_locations.insert(n, (e.name.clone(), + extern_location(e, &cx.dst))); let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID }; cache.paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); } @@ -1343,22 +1344,43 @@ impl<'a> Item<'a> { /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. fn href(&self, cx: &Context) -> 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) + }; + + // 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.clone(), + 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. - if ast_util::is_local(self.item.def_id) { + } else if ast_util::is_local(self.item.def_id) { let mut path = Vec::new(); clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename), true, |component| { path.push(component.to_string()); }); - 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) - }; Some(format!("{root}src/{krate}/{path}.html#{href}", root = self.cx.root_path, krate = self.cx.layout.krate, @@ -1380,9 +1402,9 @@ impl<'a> Item<'a> { let cache = cache(); let path = &cache.external_paths[&self.item.def_id]; let root = match cache.extern_locations[&self.item.def_id.krate] { - Remote(ref s) => s.to_string(), - Local => self.cx.root_path.clone(), - Unknown => return None, + (_, Remote(ref s)) => s.to_string(), + (_, Local) => self.cx.root_path.clone(), + (_, Unknown) => return None, }; Some(format!("{root}{path}/{file}?gotosrc={goto}", root = root, @@ -1444,7 +1466,8 @@ impl<'a> fmt::Display for Item<'a> { if self.cx.include_sources && !is_primitive { match self.href(self.cx) { Some(l) => { - try!(write!(fmt, "[src]", + try!(write!(fmt, "[src]", self.item.def_id.node, l)); } None => {} diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index c3ab375a9e2..0379c04be4d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -802,6 +802,9 @@ if (query['gotosrc']) { window.location = $('#src-' + query['gotosrc']).attr('href'); } + if (query['gotomacrosrc']) { + window.location = $('.srclink').attr('href'); + } $("#expand-all").on("click", function() { $(".docblock").show(); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e4f4dbaafbe..4ad693578cc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -398,6 +398,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: def.ident, whence: def.span, stab: self.stability(def.id), + imported_from: def.imported_from, } } }