Skip to content

Commit e833cd3

Browse files
Improve automatic_links globally
1 parent 6fdd98d commit e833cd3

File tree

5 files changed

+163
-37
lines changed

5 files changed

+163
-37
lines changed

compiler/rustc_session/src/lint/builtin.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1892,14 +1892,14 @@ declare_lint! {
18921892
}
18931893

18941894
declare_lint! {
1895-
/// The `automatic_links` lint detects when a URL/email address could be
1896-
/// written using only angle brackets. This is a `rustdoc` only lint, see
1897-
/// the documentation in the [rustdoc book].
1895+
/// The `automatic_links` lint detects when a URL could be written using
1896+
/// only angle brackets. This is a `rustdoc` only lint, see the
1897+
/// documentation in the [rustdoc book].
18981898
///
18991899
/// [rustdoc book]: ../../../rustdoc/lints.html#automatic_links
19001900
pub AUTOMATIC_LINKS,
1901-
Allow,
1902-
"detects URLs/email adresses that could be written using only angle brackets"
1901+
Warn,
1902+
"detects URLs that could be written using only angle brackets"
19031903
}
19041904

19051905
declare_lint! {

src/doc/rustdoc/src/lints.md

+3-10
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,10 @@ warning: 2 warnings emitted
288288

289289
## automatic_links
290290

291-
This link is **allowed by default** and is **nightly-only**. It detects links
292-
which could use the "automatic" link syntax. For example:
291+
This lint is **nightly-only** and **warns by default**. It detects links which
292+
could use the "automatic" link syntax. For example:
293293

294294
```rust
295-
#![warn(automatic_links)]
296-
297295
/// http://hello.rs
298296
/// [http://a.com](http://a.com)
299297
/// [http://b.com]
@@ -305,17 +303,12 @@ pub fn foo() {}
305303
Which will give:
306304

307305
```text
308-
warning: won't be a link as is
306+
warning: this URL is not a hyperlink
309307
--> foo.rs:3:5
310308
|
311309
3 | /// http://hello.rs
312310
| ^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://hello.rs>`
313311
|
314-
note: the lint level is defined here
315-
--> foo.rs:1:9
316-
|
317-
1 | #![warn(automatic_links)]
318-
| ^^^^^^^^^^^^^^^
319312
320313
warning: unneeded long form for URL
321314
--> foo.rs:4:5

src/librustdoc/passes/automatic_links.rs

+18-19
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ use rustc_session::lint;
1313
pub const CHECK_AUTOMATIC_LINKS: Pass = Pass {
1414
name: "check-automatic-links",
1515
run: check_automatic_links,
16-
description: "detects URLS/email addresses that could be written using angle brackets",
16+
description: "detects URLS that could be written using angle brackets",
1717
};
1818

19-
const URL_REGEX: &str =
20-
r"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)";
19+
const URL_REGEX: &str = concat!(
20+
r"https?://", // url scheme
21+
r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
22+
r"[a-zA-Z]{2,4}", // root domain
23+
r"\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)" // optional query or url fragments
24+
);
2125

2226
struct AutomaticLinksLinter<'a, 'tcx> {
2327
cx: &'a DocContext<'tcx>,
@@ -35,22 +39,16 @@ impl<'a, 'tcx> AutomaticLinksLinter<'a, 'tcx> {
3539
range: Range<usize>,
3640
f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>),
3741
) {
38-
for (pos, c) in text.char_indices() {
39-
// For now, we only check "full" URLs.
40-
if c == 'h' {
41-
let text = &text[pos..];
42-
if text.starts_with("http://") || text.starts_with("https://") {
43-
if let Some(m) = self.regex.find(text) {
44-
let url = &text[..m.end()];
45-
f(
46-
self.cx,
47-
"won't be a link as is",
48-
url,
49-
Range { start: range.start + pos, end: range.start + pos + m.end() },
50-
)
51-
}
52-
}
53-
}
42+
// For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
43+
for match_ in self.regex.find_iter(&text) {
44+
let url = match_.as_str();
45+
let url_range = match_.range();
46+
f(
47+
self.cx,
48+
"this URL is not a hyperlink",
49+
url,
50+
Range { start: range.start + url_range.start, end: range.start + url_range.end },
51+
);
5452
}
5553
}
5654
}
@@ -106,6 +104,7 @@ impl<'a, 'tcx> DocFolder for AutomaticLinksLinter<'a, 'tcx> {
106104
}
107105
Event::End(Tag::Link(_, url, _)) => {
108106
in_link = false;
107+
// NOTE: links cannot be nested, so we don't need to check `kind`
109108
if url.as_ref() == title && !ignore {
110109
report_diag(self.cx, "unneeded long form for URL", &url, range);
111110
}

src/test/rustdoc-ui/automatic-links.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,40 @@
1010
/// [http://c.com][http://c.com]
1111
pub fn a() {}
1212

13+
/// https://somewhere.com
14+
//~^ ERROR this URL is not a hyperlink
15+
/// https://somewhere.com/a
16+
//~^ ERROR this URL is not a hyperlink
17+
/// https://www.somewhere.com
18+
//~^ ERROR this URL is not a hyperlink
19+
/// https://www.somewhere.com/a
20+
//~^ ERROR this URL is not a hyperlink
21+
/// https://subdomain.example.com
22+
//~^ ERROR not a hyperlink
23+
/// https://somewhere.com?
24+
//~^ ERROR this URL is not a hyperlink
25+
/// https://somewhere.com/a?
26+
//~^ ERROR this URL is not a hyperlink
1327
/// https://somewhere.com?hello=12
14-
//~^ ERROR won't be a link as is
28+
//~^ ERROR this URL is not a hyperlink
29+
/// https://somewhere.com/a?hello=12
30+
//~^ ERROR this URL is not a hyperlink
31+
/// https://example.com?hello=12#xyz
32+
//~^ ERROR this URL is not a hyperlink
33+
/// https://example.com/a?hello=12#xyz
34+
//~^ ERROR this URL is not a hyperlink
35+
/// https://example.com#xyz
36+
//~^ ERROR this URL is not a hyperlink
37+
/// https://example.com/a#xyz
38+
//~^ ERROR this URL is not a hyperlink
39+
/// https://somewhere.com?hello=12&bye=11
40+
//~^ ERROR this URL is not a hyperlink
41+
/// https://somewhere.com/a?hello=12&bye=11
42+
//~^ ERROR this URL is not a hyperlink
43+
/// https://somewhere.com?hello=12&bye=11#xyz
44+
//~^ ERROR this URL is not a hyperlink
45+
/// hey! https://somewhere.com/a?hello=12&bye=11#xyz
46+
//~^ ERROR this URL is not a hyperlink
1547
pub fn c() {}
1648

1749
/// <https://somewhere.com>
@@ -20,3 +52,9 @@ pub fn c() {}
2052
///
2153
/// [b]: http://b.com
2254
pub fn everything_is_fine_here() {}
55+
56+
#[allow(automatic_links)]
57+
pub mod foo {
58+
/// https://somewhere.com/a?hello=12&bye=11#xyz
59+
pub fn bar() {}
60+
}

src/test/rustdoc-ui/automatic-links.stderr

+98-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,107 @@ error: unneeded long form for URL
1616
LL | /// [http://b.com]
1717
| ^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://b.com>`
1818

19-
error: won't be a link as is
19+
error: this URL is not a hyperlink
2020
--> $DIR/automatic-links.rs:13:5
2121
|
22+
LL | /// https://somewhere.com
23+
| ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com>`
24+
25+
error: this URL is not a hyperlink
26+
--> $DIR/automatic-links.rs:15:5
27+
|
28+
LL | /// https://somewhere.com/a
29+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a>`
30+
31+
error: this URL is not a hyperlink
32+
--> $DIR/automatic-links.rs:17:5
33+
|
34+
LL | /// https://www.somewhere.com
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://www.somewhere.com>`
36+
37+
error: this URL is not a hyperlink
38+
--> $DIR/automatic-links.rs:19:5
39+
|
40+
LL | /// https://www.somewhere.com/a
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://www.somewhere.com/a>`
42+
43+
error: this URL is not a hyperlink
44+
--> $DIR/automatic-links.rs:21:5
45+
|
46+
LL | /// https://subdomain.example.com
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://subdomain.example.com>`
48+
49+
error: this URL is not a hyperlink
50+
--> $DIR/automatic-links.rs:23:5
51+
|
52+
LL | /// https://somewhere.com?
53+
| ^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?>`
54+
55+
error: this URL is not a hyperlink
56+
--> $DIR/automatic-links.rs:25:5
57+
|
58+
LL | /// https://somewhere.com/a?
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?>`
60+
61+
error: this URL is not a hyperlink
62+
--> $DIR/automatic-links.rs:27:5
63+
|
2264
LL | /// https://somewhere.com?hello=12
2365
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12>`
2466

25-
error: aborting due to 3 previous errors
67+
error: this URL is not a hyperlink
68+
--> $DIR/automatic-links.rs:29:5
69+
|
70+
LL | /// https://somewhere.com/a?hello=12
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12>`
72+
73+
error: this URL is not a hyperlink
74+
--> $DIR/automatic-links.rs:31:5
75+
|
76+
LL | /// https://example.com?hello=12#xyz
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com?hello=12#xyz>`
78+
79+
error: this URL is not a hyperlink
80+
--> $DIR/automatic-links.rs:33:5
81+
|
82+
LL | /// https://example.com/a?hello=12#xyz
83+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com/a?hello=12#xyz>`
84+
85+
error: this URL is not a hyperlink
86+
--> $DIR/automatic-links.rs:35:5
87+
|
88+
LL | /// https://example.com#xyz
89+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com#xyz>`
90+
91+
error: this URL is not a hyperlink
92+
--> $DIR/automatic-links.rs:37:5
93+
|
94+
LL | /// https://example.com/a#xyz
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://example.com/a#xyz>`
96+
97+
error: this URL is not a hyperlink
98+
--> $DIR/automatic-links.rs:39:5
99+
|
100+
LL | /// https://somewhere.com?hello=12&bye=11
101+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12&bye=11>`
102+
103+
error: this URL is not a hyperlink
104+
--> $DIR/automatic-links.rs:41:5
105+
|
106+
LL | /// https://somewhere.com/a?hello=12&bye=11
107+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12&bye=11>`
108+
109+
error: this URL is not a hyperlink
110+
--> $DIR/automatic-links.rs:43:5
111+
|
112+
LL | /// https://somewhere.com?hello=12&bye=11#xyz
113+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com?hello=12&bye=11#xyz>`
114+
115+
error: this URL is not a hyperlink
116+
--> $DIR/automatic-links.rs:45:10
117+
|
118+
LL | /// hey! https://somewhere.com/a?hello=12&bye=11#xyz
119+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com/a?hello=12&bye=11#xyz>`
120+
121+
error: aborting due to 19 previous errors
26122

0 commit comments

Comments
 (0)