about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-13 15:25:40 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-16 09:44:33 -0700
commit8fb31f75c95c52cfef40c6ffe2f1452c959ca5e4 (patch)
treeae4a77128625aa008da5b569b3b641c88f73e97f
parent0a46933c4d81573e78ce16cd215ba155a3114fce (diff)
downloadrust-8fb31f75c95c52cfef40c6ffe2f1452c959ca5e4.tar.gz
rust-8fb31f75c95c52cfef40c6ffe2f1452c959ca5e4.zip
rustdoc: Fix cross-crate macro source links
The source filename for cross crate macros isn't quite right so the normal
generated links are invalid.

Closes #21311
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/doctree.rs1
-rw-r--r--src/librustdoc/html/format.rs12
-rw-r--r--src/librustdoc/html/render.rs51
-rw-r--r--src/librustdoc/html/static/main.js3
-rw-r--r--src/librustdoc/visit_ast.rs1
6 files changed, 51 insertions, 20 deletions
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<Item> 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<ast::DefId> {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Macro {
     pub source: String,
+    pub imported_from: Option<String>,
 }
 
 impl Clean<Item> for doctree::Macro {
@@ -2570,6 +2572,7 @@ impl Clean<Item> 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<ast::Attribute>,
     pub whence: Span,
     pub stab: Option<attr::Stability>,
+    pub imported_from: Option<Ident>,
 }
 
 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<String>)> {
         repeat("../").take(loc.len()).collect::<String>()
     } else {
         match cache.extern_locations[&did.krate] {
-            render::Remote(ref s) => s.to_string(),
-            render::Local => repeat("../").take(loc.len()).collect::<String>(),
-            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::<String>())
                 }
-                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<ast::DefId, Vec<Implementor>>,
 
     /// Cache of where external crate documentation can be found.
-    pub extern_locations: HashMap<ast::CrateNum, ExternalLocation>,
+    pub extern_locations: HashMap<ast::CrateNum, (String, ExternalLocation)>,
 
     /// Cache of where documentation for primitives can be found.
     pub primitive_locations: HashMap<clean::PrimitiveType, ast::CrateNum>,
@@ -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<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)
+        };
+
+        // 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, "<a id='src-{}' href='{}'>[src]</a>",
+                    try!(write!(fmt, "<a id='src-{}' class='srclink' \
+                                       href='{}'>[src]</a>",
                                 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,
         }
     }
 }