@@ -21,6 +21,9 @@ use std::fs;
21
21
use std:: path:: { Component , Path , PathBuf } ;
22
22
use std:: rc:: Rc ;
23
23
24
+ use once_cell:: sync:: Lazy ;
25
+ use regex:: Regex ;
26
+
24
27
use crate :: Redirect :: * ;
25
28
26
29
// Add linkcheck exceptions here
@@ -50,6 +53,44 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
50
53
( "alloc/collections/btree_set/struct.BTreeSet.html" , & [ "#insert-and-complex-keys" ] ) ,
51
54
] ;
52
55
56
+ #[ rustfmt:: skip]
57
+ const INTRA_DOC_LINK_EXCEPTIONS : & [ ( & str , & [ & str ] ) ] = & [
58
+ // This will never have links that are not in other pages.
59
+ // To avoid repeating the exceptions twice, an empty list means all broken links are allowed.
60
+ ( "reference/print.html" , & [ ] ) ,
61
+ // All the reference 'links' are actually ENBF highlighted as code
62
+ ( "reference/comments.html" , & [
63
+ "/</code> <code>!" ,
64
+ "*</code> <code>!" ,
65
+ ] ) ,
66
+ ( "reference/identifiers.html" , & [
67
+ "a</code>-<code>z</code> <code>A</code>-<code>Z" ,
68
+ "a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_" ,
69
+ "a</code>-<code>z</code> <code>A</code>-<code>Z</code>] [<code>a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_" ,
70
+ ] ) ,
71
+ ( "reference/tokens.html" , & [
72
+ "0</code>-<code>1" ,
73
+ "0</code>-<code>7" ,
74
+ "0</code>-<code>9" ,
75
+ "0</code>-<code>9" ,
76
+ "0</code>-<code>9</code> <code>a</code>-<code>f</code> <code>A</code>-<code>F" ,
77
+ ] ) ,
78
+ ( "reference/notation.html" , & [
79
+ "b</code> <code>B" ,
80
+ "a</code>-<code>z" ,
81
+ ] ) ,
82
+ // This is being used in the sense of 'inclusive range', not a markdown link
83
+ ( "core/ops/struct.RangeInclusive.html" , & [ "begin</code>, <code>end" ] ) ,
84
+ ( "std/ops/struct.RangeInclusive.html" , & [ "begin</code>, <code>end" ] ) ,
85
+ ( "core/slice/trait.SliceIndex.html" , & [ "begin</code>, <code>end" ] ) ,
86
+ ( "alloc/slice/trait.SliceIndex.html" , & [ "begin</code>, <code>end" ] ) ,
87
+ ( "std/slice/trait.SliceIndex.html" , & [ "begin</code>, <code>end" ] ) ,
88
+
89
+ ] ;
90
+
91
+ static BROKEN_INTRA_DOC_LINK : Lazy < Regex > =
92
+ Lazy :: new ( || Regex :: new ( r#"\[<code>(.*)</code>\]"# ) . unwrap ( ) ) ;
93
+
53
94
macro_rules! t {
54
95
( $e: expr) => {
55
96
match $e {
@@ -138,6 +179,14 @@ fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) {
138
179
}
139
180
}
140
181
182
+ fn is_intra_doc_exception ( file : & Path , link : & str ) -> bool {
183
+ if let Some ( entry) = INTRA_DOC_LINK_EXCEPTIONS . iter ( ) . find ( |& ( f, _) | file. ends_with ( f) ) {
184
+ entry. 1 . is_empty ( ) || entry. 1 . contains ( & link)
185
+ } else {
186
+ false
187
+ }
188
+ }
189
+
141
190
fn is_exception ( file : & Path , link : & str ) -> bool {
142
191
if let Some ( entry) = LINKCHECK_EXCEPTIONS . iter ( ) . find ( |& ( f, _) | file. ends_with ( f) ) {
143
192
entry. 1 . contains ( & link)
@@ -292,6 +341,19 @@ fn check(cache: &mut Cache, root: &Path, file: &Path, errors: &mut bool) -> Opti
292
341
}
293
342
}
294
343
} ) ;
344
+
345
+ // Search for intra-doc links that rustdoc didn't warn about
346
+ // FIXME(#77199, 77200) Rustdoc should just warn about these directly.
347
+ // NOTE: only looks at one line at a time; in practice this should find most links
348
+ for ( i, line) in contents. lines ( ) . enumerate ( ) {
349
+ for broken_link in BROKEN_INTRA_DOC_LINK . captures_iter ( line) {
350
+ if !is_intra_doc_exception ( file, & broken_link[ 1 ] ) {
351
+ * errors = true ;
352
+ print ! ( "{}:{}: broken intra-doc link - " , pretty_file. display( ) , i + 1 ) ;
353
+ println ! ( "{}" , & broken_link[ 0 ] ) ;
354
+ }
355
+ }
356
+ }
295
357
Some ( pretty_file)
296
358
}
297
359
0 commit comments