about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-06-12 22:08:43 +0200
committerGuillaume Gomez <guillaume.gomez@huawei.com>2021-08-05 23:08:29 +0200
commitfd69fa8670aaf67cde504acd097a2b4ddc74f88a (patch)
treeeea498abfa4f9a2cda08f0c3bdc95240f6367952
parent1a48d1a4de1e26e08780a026daed3c7db743ff2f (diff)
downloadrust-fd69fa8670aaf67cde504acd097a2b4ddc74f88a.tar.gz
rust-fd69fa8670aaf67cde504acd097a2b4ddc74f88a.zip
Add missing root_path when generating links using href
-rw-r--r--src/librustdoc/html/format.rs18
-rw-r--r--src/librustdoc/html/highlight.rs9
-rw-r--r--src/librustdoc/html/render/span_map.rs1
-rw-r--r--src/test/rustdoc/auxiliary/source_code.rs1
-rw-r--r--src/test/rustdoc/check-source-code-urls-to-def.rs11
5 files changed, 35 insertions, 5 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 8ab6aa775d2..eb7c12d13c3 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -484,7 +484,11 @@ crate enum HrefError {
     NotInExternalCache,
 }
 
-crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<String>), HrefError> {
+crate fn href_with_root_path(
+    did: DefId,
+    cx: &Context<'_>,
+    root_path: Option<&str>,
+) -> Result<(String, ItemType, Vec<String>), HrefError> {
     let cache = &cx.cache();
     let relative_to = &cx.current;
     fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
@@ -495,6 +499,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<Str
         return Err(HrefError::Private);
     }
 
+    let mut is_remote = false;
     let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
         Some(&(ref fqp, shortty)) => (fqp, shortty, {
             let module_fqp = to_module_fqp(shortty, fqp);
@@ -508,6 +513,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<Str
                     shortty,
                     match cache.extern_locations[&did.krate] {
                         ExternalLocation::Remote(ref s) => {
+                            is_remote = true;
                             let s = s.trim_end_matches('/');
                             let mut s = vec![s];
                             s.extend(module_fqp[..].iter().map(String::as_str));
@@ -522,6 +528,12 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<Str
             }
         }
     };
+    if !is_remote {
+        if let Some(root_path) = root_path {
+            let root = root_path.trim_end_matches('/');
+            url_parts.insert(0, root);
+        }
+    }
     let last = &fqp.last().unwrap()[..];
     let filename;
     match shortty {
@@ -536,6 +548,10 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<Str
     Ok((url_parts.join("/"), shortty, fqp.to_vec()))
 }
 
+crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<String>), HrefError> {
+    href_with_root_path(did, cx, None)
+}
+
 /// Both paths should only be modules.
 /// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
 /// both need `../iter/trait.Iterator.html` to get at the iterator trait.
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 9adb95fe90e..47c870645ac 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -580,12 +580,19 @@ fn string<T: Display>(
         if let Some(href) =
             context_info.context.shared.span_correspondance_map.get(&def_span).and_then(|href| {
                 let context = context_info.context;
+                // FIXME: later on, it'd be nice to provide two links (if possible) for all items:
+                // one to the documentation page and one to the source definition.
+                // FIXME: currently, external items only generate a link to their documentation,
+                // a link to their definition can be generated using this:
+                // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
                 match href {
                     LinkFromSrc::Local(span) => context
                         .href_from_span(*span)
                         .map(|s| format!("{}{}", context_info.root_path, s)),
                     LinkFromSrc::External(def_id) => {
-                        format::href(*def_id, context).map(|(url, _, _)| url)
+                        format::href_with_root_path(*def_id, context, Some(context_info.root_path))
+                            .ok()
+                            .map(|(url, _, _)| url)
                     }
                 }
             })
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index e168e41b832..b60f5f433f7 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -110,6 +110,7 @@ impl<'tcx> SpanMapVisitor<'tcx> {
                 Some(def_id)
             }
             Res::Local(_) => None,
+            Res::Err => return,
             _ => return,
         };
         if let Some(span) = self.tcx.hir().res_span(path.res) {
diff --git a/src/test/rustdoc/auxiliary/source_code.rs b/src/test/rustdoc/auxiliary/source_code.rs
new file mode 100644
index 00000000000..72a5c1a0ae9
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/source_code.rs
@@ -0,0 +1 @@
+pub struct SourceCode;
diff --git a/src/test/rustdoc/check-source-code-urls-to-def.rs b/src/test/rustdoc/check-source-code-urls-to-def.rs
index 5caef29fede..51c4835b5aa 100644
--- a/src/test/rustdoc/check-source-code-urls-to-def.rs
+++ b/src/test/rustdoc/check-source-code-urls-to-def.rs
@@ -1,7 +1,11 @@
 // compile-flags: -Zunstable-options --generate-link-to-definition
+// aux-build:source_code.rs
+// build-aux-docs
 
 #![crate_name = "foo"]
 
+extern crate source_code;
+
 // @has 'src/foo/check-source-code-urls-to-def.rs.html'
 
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#1-17"]' 'bar'
@@ -23,13 +27,14 @@ impl Foo {
 fn babar() {}
 
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html"]' 'String'
-// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#17"]' 5
-pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar) {
+// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
+// @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
+pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
     let x = 12;
     let y: Foo = Foo;
     let z: Bar = bar::Bar { field: Foo };
     babar();
-    // @has - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#20"]' 'hello'
+    // @has - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#24"]' 'hello'
     y.hello();
 }