@@ -6,18 +6,7 @@ use rustc_span::{BytePos, Span};
66use super :: DOC_BROKEN_LINK ;
77
88pub fn check ( cx : & LateContext < ' _ > , attrs : & [ Attribute ] ) {
9- for broken_link in BrokenLinkLoader :: collect_broken_links ( attrs) {
10- let reason_msg = match broken_link. reason {
11- BrokenLinkReason :: MultipleLines => "broken across multiple lines" ,
12- } ;
13-
14- span_lint (
15- cx,
16- DOC_BROKEN_LINK ,
17- broken_link. span ,
18- format ! ( "possible broken doc link: {reason_msg}" ) ,
19- ) ;
20- }
9+ BrokenLinkReporter :: warn_if_broken_links ( cx, attrs) ;
2110}
2211
2312/// The reason why a link is considered broken.
@@ -49,11 +38,9 @@ enum UrlState {
4938}
5039
5140/// Scan AST attributes looking up in doc comments for broken links
52- /// which rustdoc won't be able to properly create link tags later.
53- struct BrokenLinkLoader {
54- /// List of detected broken links.
55- broken_links : Vec < BrokenLink > ,
56-
41+ /// which rustdoc won't be able to properly create link tags later,
42+ /// and warn about those failures.
43+ struct BrokenLinkReporter {
5744 state : Option < State > ,
5845
5946 /// Keep track of the span for the processing broken link.
@@ -63,30 +50,24 @@ struct BrokenLinkLoader {
6350 active_pos_start : u32 ,
6451}
6552
66- impl BrokenLinkLoader {
67- /// Return broken links.
68- fn collect_broken_links ( attrs : & [ Attribute ] ) -> Vec < BrokenLink > {
69- let mut loader = BrokenLinkLoader {
70- broken_links : vec ! [ ] ,
53+ impl BrokenLinkReporter {
54+ fn warn_if_broken_links ( cx : & LateContext < ' _ > , attrs : & [ Attribute ] ) {
55+ let mut reporter = BrokenLinkReporter {
7156 state : None ,
7257 active_pos_start : 0 ,
7358 active_span : None ,
7459 } ;
75- loader. scan_attrs ( attrs) ;
76- loader. broken_links
77- }
7860
79- fn scan_attrs ( & mut self , attrs : & [ Attribute ] ) {
8061 for attr in attrs {
8162 if let AttrKind :: DocComment ( _com_kind, sym) = attr. kind
8263 && let AttrStyle :: Outer = attr. style
8364 {
84- self . scan_line ( sym. as_str ( ) , attr. span ) ;
65+ reporter . scan_line ( cx , sym. as_str ( ) , attr. span ) ;
8566 }
8667 }
8768 }
8869
89- fn scan_line ( & mut self , line : & str , attr_span : Span ) {
70+ fn scan_line ( & mut self , cx : & LateContext < ' _ > , line : & str , attr_span : Span ) {
9071 // Note that we specifically need the char _byte_ indices here, not the positional indexes
9172 // within the char array to deal with multi-byte characters properly. `char_indices` does
9273 // exactly that. It provides an iterator over tuples of the form `(byte position, char)`.
@@ -131,7 +112,7 @@ impl BrokenLinkLoader {
131112 if let UrlState :: FilledBrokenMultipleLines = url_state {
132113 // +3 skips the opening delimiter and +1 to include the closing parethesis
133114 let pos_end = attr_span. lo ( ) . 0 + u32:: try_from ( pos) . unwrap ( ) + 4 ;
134- self . record_broken_link ( pos_end, BrokenLinkReason :: MultipleLines ) ;
115+ self . record_broken_link ( cx , pos_end, BrokenLinkReason :: MultipleLines ) ;
135116 self . reset_lookup ( ) ;
136117 }
137118 self . reset_lookup ( ) ;
@@ -159,14 +140,23 @@ impl BrokenLinkLoader {
159140 self . active_pos_start = 0 ;
160141 }
161142
162- fn record_broken_link ( & mut self , pos_end : u32 , reason : BrokenLinkReason ) {
143+ fn record_broken_link ( & mut self , cx : & LateContext < ' _ > , pos_end : u32 , reason : BrokenLinkReason ) {
163144 if let Some ( attr_span) = self . active_span {
164145 let start = BytePos ( self . active_pos_start ) ;
165146 let end = BytePos ( pos_end) ;
166147
167148 let span = Span :: new ( start, end, attr_span. ctxt ( ) , attr_span. parent ( ) ) ;
168149
169- self . broken_links . push ( BrokenLink { reason, span } ) ;
150+ let reason_msg = match reason {
151+ BrokenLinkReason :: MultipleLines => "broken across multiple lines" ,
152+ } ;
153+
154+ span_lint (
155+ cx,
156+ DOC_BROKEN_LINK ,
157+ span,
158+ format ! ( "possible broken doc link: {reason_msg}" ) ,
159+ ) ;
170160 }
171161 }
172162}
0 commit comments