Skip to content

Commit 32ed5ac

Browse files
Rollup merge of rust-lang#51391 - estebank:docspan, r=GuillaumeGomez
Use spans pointing at the inside of a rustdoc attribute Follow up to rust-lang#51111. Point to the link in a rustdoc attribute where intralink resolution failed, instead of the full rustdoc attribute's span. r? @GuillaumeGomez cc @kennytm
2 parents 4b176b2 + 31bb50b commit 32ed5ac

File tree

3 files changed

+177
-43
lines changed

3 files changed

+177
-43
lines changed

src/librustdoc/clean/mod.rs

+46-16
Original file line numberDiff line numberDiff line change
@@ -1251,30 +1251,60 @@ fn resolution_failure(
12511251
link_range: Option<Range<usize>>,
12521252
) {
12531253
let sp = span_of_attrs(attrs);
1254-
let mut diag = cx.sess()
1255-
.struct_span_warn(sp, &format!("[{}] cannot be resolved, ignoring it...", path_str));
1254+
let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
12561255

1257-
if let Some(link_range) = link_range {
1256+
let code_dox = sp.to_src(cx);
1257+
1258+
let doc_comment_padding = 3;
1259+
let mut diag = if let Some(link_range) = link_range {
12581260
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
12591261
// ^ ~~~~~~
12601262
// | link_range
12611263
// last_new_line_offset
12621264

1263-
let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
1264-
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
1265-
1266-
// Print the line containing the `link_range` and manually mark it with '^'s
1267-
diag.note(&format!(
1268-
"the link appears in this line:\n\n{line}\n{indicator: <before$}{indicator:^<found$}",
1269-
line=line,
1270-
indicator="",
1271-
before=link_range.start - last_new_line_offset,
1272-
found=link_range.len(),
1273-
));
1274-
} else {
1265+
let mut diag;
1266+
if dox.lines().count() == code_dox.lines().count() {
1267+
let line_offset = dox[..link_range.start].lines().count();
1268+
// The span starts in the `///`, so we don't have to account for the leading whitespace
1269+
let code_dox_len = if line_offset <= 1 {
1270+
doc_comment_padding
1271+
} else {
1272+
// The first `///`
1273+
doc_comment_padding +
1274+
// Each subsequent leading whitespace and `///`
1275+
code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
1276+
sum + doc_comment_padding + line.len() - line.trim().len()
1277+
})
1278+
};
12751279

1276-
}
1280+
// Extract the specific span
1281+
let sp = sp.from_inner_byte_pos(
1282+
link_range.start + code_dox_len,
1283+
link_range.end + code_dox_len,
1284+
);
12771285

1286+
diag = cx.sess().struct_span_warn(sp, &msg);
1287+
diag.span_label(sp, "cannot be resolved, ignoring");
1288+
} else {
1289+
diag = cx.sess().struct_span_warn(sp, &msg);
1290+
1291+
let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
1292+
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
1293+
1294+
// Print the line containing the `link_range` and manually mark it with '^'s
1295+
diag.note(&format!(
1296+
"the link appears in this line:\n\n{line}\n\
1297+
{indicator: <before$}{indicator:^<found$}",
1298+
line=line,
1299+
indicator="",
1300+
before=link_range.start - last_new_line_offset,
1301+
found=link_range.len(),
1302+
));
1303+
}
1304+
diag
1305+
} else {
1306+
cx.sess().struct_span_warn(sp, &msg)
1307+
};
12781308
diag.emit();
12791309
}
12801310

src/test/rustdoc-ui/intra-links-warning.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,48 @@
1010

1111
// compile-pass
1212

13-
//! Test with [Foo::baz], [Bar::foo], ...
14-
//!
15-
//! and [Uniooon::X].
13+
//! Test with [Foo::baz], [Bar::foo], ...
14+
//! , [Uniooon::X] and [Qux::Z].
15+
//!
16+
//! , [Uniooon::X] and [Qux::Z].
1617
18+
/// [Qux:Y]
1719
pub struct Foo {
1820
pub bar: usize,
1921
}
22+
23+
/// Foo
24+
/// bar [BarA] bar
25+
/// baz
26+
pub fn a() {}
27+
28+
/**
29+
* Foo
30+
* bar [BarB] bar
31+
* baz
32+
*/
33+
pub fn b() {}
34+
35+
/** Foo
36+
37+
bar [BarC] bar
38+
baz
39+
40+
let bar_c_1 = 0;
41+
let bar_c_2 = 0;
42+
let g = [bar_c_1];
43+
let h = g[bar_c_2];
44+
45+
*/
46+
pub fn c() {}
47+
48+
#[doc = "Foo\nbar [BarD] bar\nbaz"]
49+
pub fn d() {}
50+
51+
macro_rules! f {
52+
($f:expr) => {
53+
#[doc = $f]
54+
pub fn f() {}
55+
}
56+
}
57+
f!("Foo\nbar [BarF] bar\nbaz");
+90-24
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,105 @@
1-
warning: [Foo::baz] cannot be resolved, ignoring it...
2-
--> $DIR/intra-links-warning.rs:13:1
1+
warning: `[Foo::baz]` cannot be resolved, ignoring it...
2+
--> $DIR/intra-links-warning.rs:13:23
33
|
4-
13 | / //! Test with [Foo::baz], [Bar::foo], ...
5-
14 | | //!
6-
15 | | //! and [Uniooon::X].
7-
| |_____________________^
4+
13 | //! Test with [Foo::baz], [Bar::foo], ...
5+
| ^^^^^^^^ cannot be resolved, ignoring
6+
7+
warning: `[Bar::foo]` cannot be resolved, ignoring it...
8+
--> $DIR/intra-links-warning.rs:13:35
9+
|
10+
13 | //! Test with [Foo::baz], [Bar::foo], ...
11+
| ^^^^^^^^ cannot be resolved, ignoring
12+
13+
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
14+
--> $DIR/intra-links-warning.rs:14:13
15+
|
16+
14 | //! , [Uniooon::X] and [Qux::Z].
17+
| ^^^^^^^^^^ cannot be resolved, ignoring
18+
19+
warning: `[Qux::Z]` cannot be resolved, ignoring it...
20+
--> $DIR/intra-links-warning.rs:14:30
21+
|
22+
14 | //! , [Uniooon::X] and [Qux::Z].
23+
| ^^^^^^ cannot be resolved, ignoring
24+
25+
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
26+
--> $DIR/intra-links-warning.rs:16:14
27+
|
28+
16 | //! , [Uniooon::X] and [Qux::Z].
29+
| ^^^^^^^^^^ cannot be resolved, ignoring
30+
31+
warning: `[Qux::Z]` cannot be resolved, ignoring it...
32+
--> $DIR/intra-links-warning.rs:16:31
33+
|
34+
16 | //! , [Uniooon::X] and [Qux::Z].
35+
| ^^^^^^ cannot be resolved, ignoring
36+
37+
warning: `[Qux:Y]` cannot be resolved, ignoring it...
38+
--> $DIR/intra-links-warning.rs:18:13
39+
|
40+
18 | /// [Qux:Y]
41+
| ^^^^^ cannot be resolved, ignoring
42+
43+
warning: `[BarA]` cannot be resolved, ignoring it...
44+
--> $DIR/intra-links-warning.rs:24:10
45+
|
46+
24 | /// bar [BarA] bar
47+
| ^^^^ cannot be resolved, ignoring
48+
49+
warning: `[BarB]` cannot be resolved, ignoring it...
50+
--> $DIR/intra-links-warning.rs:28:1
51+
|
52+
28 | / /**
53+
29 | | * Foo
54+
30 | | * bar [BarB] bar
55+
31 | | * baz
56+
32 | | */
57+
| |___^
58+
|
59+
= note: the link appears in this line:
60+
61+
bar [BarB] bar
62+
^^^^
63+
64+
warning: `[BarC]` cannot be resolved, ignoring it...
65+
--> $DIR/intra-links-warning.rs:35:1
66+
|
67+
35 | / /** Foo
68+
36 | |
69+
37 | | bar [BarC] bar
70+
38 | | baz
71+
... |
72+
44 | |
73+
45 | | */
74+
| |__^
875
|
976
= note: the link appears in this line:
1077

11-
Test with [Foo::baz], [Bar::foo], ...
12-
^^^^^^^^
78+
bar [BarC] bar
79+
^^^^
1380

14-
warning: [Bar::foo] cannot be resolved, ignoring it...
15-
--> $DIR/intra-links-warning.rs:13:1
81+
warning: `[BarD]` cannot be resolved, ignoring it...
82+
--> $DIR/intra-links-warning.rs:48:1
1683
|
17-
13 | / //! Test with [Foo::baz], [Bar::foo], ...
18-
14 | | //!
19-
15 | | //! and [Uniooon::X].
20-
| |_____________________^
84+
48 | #[doc = "Foo/nbar [BarD] bar/nbaz"]
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2186
|
2287
= note: the link appears in this line:
2388

24-
Test with [Foo::baz], [Bar::foo], ...
25-
^^^^^^^^
89+
bar [BarD] bar
90+
^^^^
2691

27-
warning: [Uniooon::X] cannot be resolved, ignoring it...
28-
--> $DIR/intra-links-warning.rs:13:1
92+
warning: `[BarF]` cannot be resolved, ignoring it...
93+
--> $DIR/intra-links-warning.rs:53:9
2994
|
30-
13 | / //! Test with [Foo::baz], [Bar::foo], ...
31-
14 | | //!
32-
15 | | //! and [Uniooon::X].
33-
| |_____________________^
95+
53 | #[doc = $f]
96+
| ^^^^^^^^^^^
97+
...
98+
57 | f!("Foo/nbar [BarF] bar/nbaz");
99+
| ------------------------------- in this macro invocation
34100
|
35101
= note: the link appears in this line:
36102

37-
and [Uniooon::X].
38-
^^^^^^^^^^
103+
bar [BarF] bar
104+
^^^^
39105

0 commit comments

Comments
 (0)