about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-06-06 09:14:09 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-06-06 09:38:47 -0700
commit7d0b6b75f05a669ee8cc76e651a654296d7d166c (patch)
tree666b2653fe9eb718bf116896227c39b7d0be5202
parent507dfd2148f68bc3bd6349d5e666b12e360a9d15 (diff)
downloadrust-7d0b6b75f05a669ee8cc76e651a654296d7d166c.tar.gz
rust-7d0b6b75f05a669ee8cc76e651a654296d7d166c.zip
When unable to sinthesize link span, fallback to previous behavior
-rw-r--r--src/librustdoc/clean/mod.rs55
-rw-r--r--src/test/rustdoc-ui/intra-links-warning.rs42
-rw-r--r--src/test/rustdoc-ui/intra-links-warning.stderr87
3 files changed, 149 insertions, 35 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8055c99ceb8..226b3627e3e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1194,9 +1194,6 @@ fn resolution_failure(
     let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
 
     let code_dox = sp.to_src(cx);
-    // The whitespace before the `///` to properly find the original span location.
-    let dox_leading_whitespace = code_dox.lines().nth(1)
-        .map(|x| x.len() - x.trim_left().len()).unwrap_or(0);
 
     let doc_comment_padding = 3;
     let mut diag = if let Some(link_range) = link_range {
@@ -1205,26 +1202,44 @@ fn resolution_failure(
         //                       |    link_range
         //                       last_new_line_offset
 
-        let line_offset = dox[..link_range.start].lines().count();
-        let code_dox_len = if line_offset <= 1 {
+        let mut diag;
+        if dox.lines().count() == code_dox.lines().count() {
+            let line_offset = dox[..link_range.start].lines().count();
             // The span starts in the `///`, so we don't have to account for the leading whitespace
-            doc_comment_padding
-        } else {
-            // The first `///`
-            doc_comment_padding +
-                // Each subsequent leading whitespace and `///`
-                (doc_comment_padding + dox_leading_whitespace)
-                // The line position inside the doc string
-                * (line_offset - 1)
-        };
+            let code_dox_len = if line_offset <= 1 {
+                doc_comment_padding
+            } else {
+                // The first `///`
+                doc_comment_padding +
+                    // Each subsequent leading whitespace and `///`
+                    code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
+                        sum + doc_comment_padding + line.len() - line.trim().len()
+                    })
+            };
 
-        // Extract the specific span
-        let lo = sp.lo() + syntax_pos::BytePos((link_range.start + code_dox_len) as u32);
-        let hi = lo + syntax_pos::BytePos(link_range.len() as u32);
-        let sp = sp.with_lo(lo).with_hi(hi);
+            // Extract the specific span
+            let lo = sp.lo() + syntax_pos::BytePos((link_range.start + code_dox_len) as u32);
+            let hi = lo + syntax_pos::BytePos(link_range.len() as u32);
+            let sp = sp.with_lo(lo).with_hi(hi);
 
-        let mut diag = cx.sess().struct_span_warn(sp, &msg);
-        diag.span_label(sp, "cannot be resolved, ignoring");
+            diag = cx.sess().struct_span_warn(sp, &msg);
+            diag.span_label(sp, "cannot be resolved, ignoring");
+        } else {
+            diag = cx.sess().struct_span_warn(sp, &msg);
+
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+            // Print the line containing the `link_range` and manually mark it with '^'s
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
+                 {indicator: <before$}{indicator:^<found$}",
+                line=line,
+                indicator="",
+                before=link_range.start - last_new_line_offset,
+                found=link_range.len(),
+            ));
+        }
         diag
     } else {
         cx.sess().struct_span_warn(sp, &msg)
diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs
index 0d886bf0972..d6bc275b57a 100644
--- a/src/test/rustdoc-ui/intra-links-warning.rs
+++ b/src/test/rustdoc-ui/intra-links-warning.rs
@@ -11,11 +11,47 @@
 // compile-pass
 
        //! Test with [Foo::baz], [Bar::foo], ...
-       //! , [Uniooon::X] and [Qux::Z].
-       //! .
-       //! , [Uniooon::X] and [Qux::Z].
+     //! , [Uniooon::X] and [Qux::Z].
+       //!
+      //! , [Uniooon::X] and [Qux::Z].
 
        /// [Qux:Y]
 pub struct Foo {
     pub bar: usize,
 }
+
+/// Foo
+/// bar [BarA] bar
+/// baz
+pub fn a() {}
+
+/**
+ * Foo
+ * bar [BarB] bar
+ * baz
+ */
+pub fn b() {}
+
+/** Foo
+
+bar [BarC] bar
+baz
+
+    let bar_c_1 = 0;
+    let bar_c_2 = 0;
+    let g = [bar_c_1];
+    let h = g[bar_c_2];
+
+*/
+pub fn c() {}
+
+#[doc = "Foo\nbar [BarD] bar\nbaz"]
+pub fn d() {}
+
+macro_rules! f {
+    ($f:expr) => {
+        #[doc = $f]
+        pub fn f() {}
+    }
+}
+f!("Foo\nbar [BarF] bar\nbaz");
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
index a5a5598ed8f..52adba5679f 100644
--- a/src/test/rustdoc-ui/intra-links-warning.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning.stderr
@@ -11,28 +11,28 @@ warning: `[Bar::foo]` cannot be resolved, ignoring it...
    |                                   ^^^^^^^^ cannot be resolved, ignoring
 
 warning: `[Uniooon::X]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:14:15
+  --> $DIR/intra-links-warning.rs:14:13
    |
-14 |        //! , [Uniooon::X] and [Qux::Z].
-   |               ^^^^^^^^^^ cannot be resolved, ignoring
+14 |      //! , [Uniooon::X] and [Qux::Z].
+   |             ^^^^^^^^^^ cannot be resolved, ignoring
 
 warning: `[Qux::Z]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:14:32
+  --> $DIR/intra-links-warning.rs:14:30
    |
-14 |        //! , [Uniooon::X] and [Qux::Z].
-   |                                ^^^^^^ cannot be resolved, ignoring
+14 |      //! , [Uniooon::X] and [Qux::Z].
+   |                              ^^^^^^ cannot be resolved, ignoring
 
 warning: `[Uniooon::X]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:16:15
+  --> $DIR/intra-links-warning.rs:16:14
    |
-16 |        //! , [Uniooon::X] and [Qux::Z].
-   |               ^^^^^^^^^^ cannot be resolved, ignoring
+16 |       //! , [Uniooon::X] and [Qux::Z].
+   |              ^^^^^^^^^^ cannot be resolved, ignoring
 
 warning: `[Qux::Z]` cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:16:32
+  --> $DIR/intra-links-warning.rs:16:31
    |
-16 |        //! , [Uniooon::X] and [Qux::Z].
-   |                                ^^^^^^ cannot be resolved, ignoring
+16 |       //! , [Uniooon::X] and [Qux::Z].
+   |                               ^^^^^^ cannot be resolved, ignoring
 
 warning: `[Qux:Y]` cannot be resolved, ignoring it...
   --> $DIR/intra-links-warning.rs:18:13
@@ -40,3 +40,66 @@ warning: `[Qux:Y]` cannot be resolved, ignoring it...
 18 |        /// [Qux:Y]
    |             ^^^^^ cannot be resolved, ignoring
 
+warning: `[BarA]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:24:10
+   |
+24 | /// bar [BarA] bar
+   |          ^^^^ cannot be resolved, ignoring
+
+warning: `[BarB]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:28:1
+   |
+28 | / /**
+29 | |  * Foo
+30 | |  * bar [BarB] bar
+31 | |  * baz
+32 | |  */
+   | |___^
+   |
+   = note: the link appears in this line:
+           
+            bar [BarB] bar
+                 ^^^^
+
+warning: `[BarC]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:35:1
+   |
+35 | / /** Foo
+36 | |
+37 | | bar [BarC] bar
+38 | | baz
+...  |
+44 | |
+45 | | */
+   | |__^
+   |
+   = note: the link appears in this line:
+           
+           bar [BarC] bar
+                ^^^^
+
+warning: `[BarD]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:48:1
+   |
+48 | #[doc = "Foo/nbar [BarD] bar/nbaz"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the link appears in this line:
+           
+           bar [BarD] bar
+                ^^^^
+
+warning: `[BarF]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:53:9
+   |
+53 |         #[doc = $f]
+   |         ^^^^^^^^^^^
+...
+57 | f!("Foo/nbar [BarF] bar/nbaz");
+   | ------------------------------- in this macro invocation
+   |
+   = note: the link appears in this line:
+           
+           bar [BarF] bar
+                ^^^^
+