@@ -4,6 +4,8 @@ use crate::core::DocContext;
4
4
use crate :: fold:: DocFolder ;
5
5
use crate :: html:: markdown:: opts;
6
6
use core:: ops:: Range ;
7
+ use std:: iter:: Peekable ;
8
+ use std:: str:: CharIndices ;
7
9
use pulldown_cmark:: { Event , Parser } ;
8
10
use rustc_feature:: UnstableFeatures ;
9
11
use rustc_session:: lint;
@@ -75,71 +77,83 @@ fn drop_tag(
75
77
}
76
78
}
77
79
78
- fn extract_tag (
80
+ fn extract_html_tag (
79
81
tags : & mut Vec < ( String , Range < usize > ) > ,
80
82
text : & str ,
81
- range : Range < usize > ,
83
+ range : & Range < usize > ,
84
+ start_pos : usize ,
85
+ iter : & mut Peekable < CharIndices < ' _ > > ,
82
86
f : & impl Fn ( & str , & Range < usize > ) ,
83
87
) {
84
- let mut iter = text. char_indices ( ) . peekable ( ) ;
88
+ let mut tag_name = String :: new ( ) ;
89
+ let mut is_closing = false ;
90
+ let mut prev_pos = start_pos;
85
91
86
- while let Some ( ( start_pos, c) ) = iter. next ( ) {
87
- if c == '<' {
88
- let mut tag_name = String :: new ( ) ;
89
- let mut is_closing = false ;
90
- let mut prev_pos = start_pos;
91
- loop {
92
- let ( pos, c) = match iter. peek ( ) {
93
- Some ( ( pos, c) ) => ( * pos, * c) ,
94
- // In case we reached the of the doc comment, we want to check that it's an
95
- // unclosed HTML tag. For example "/// <h3".
96
- None => ( prev_pos, '\0' ) ,
97
- } ;
98
- prev_pos = pos;
99
- // Checking if this is a closing tag (like `</a>` for `<a>`).
100
- if c == '/' && tag_name. is_empty ( ) {
101
- is_closing = true ;
102
- } else if c. is_ascii_alphanumeric ( ) {
103
- tag_name. push ( c) ;
104
- } else {
105
- if !tag_name. is_empty ( ) {
106
- let mut r =
107
- Range { start : range. start + start_pos, end : range. start + pos } ;
108
- if c == '>' {
109
- // In case we have a tag without attribute, we can consider the span to
110
- // refer to it fully.
111
- r. end += 1 ;
92
+ loop {
93
+ let ( pos, c) = match iter. peek ( ) {
94
+ Some ( ( pos, c) ) => ( * pos, * c) ,
95
+ // In case we reached the of the doc comment, we want to check that it's an
96
+ // unclosed HTML tag. For example "/// <h3".
97
+ None => ( prev_pos, '\0' ) ,
98
+ } ;
99
+ prev_pos = pos;
100
+ // Checking if this is a closing tag (like `</a>` for `<a>`).
101
+ if c == '/' && tag_name. is_empty ( ) {
102
+ is_closing = true ;
103
+ } else if c. is_ascii_alphanumeric ( ) {
104
+ tag_name. push ( c) ;
105
+ } else {
106
+ if !tag_name. is_empty ( ) {
107
+ let mut r =
108
+ Range { start : range. start + start_pos, end : range. start + pos } ;
109
+ if c == '>' {
110
+ // In case we have a tag without attribute, we can consider the span to
111
+ // refer to it fully.
112
+ r. end += 1 ;
113
+ }
114
+ if is_closing {
115
+ // In case we have "</div >" or even "</div >".
116
+ if c != '>' {
117
+ if !c. is_whitespace ( ) {
118
+ // It seems like it's not a valid HTML tag.
119
+ break ;
112
120
}
113
- if is_closing {
114
- // In case we have "</div >" or even "</div >".
115
- if c != '>' {
116
- if !c. is_whitespace ( ) {
117
- // It seems like it's not a valid HTML tag.
118
- break ;
119
- }
120
- let mut found = false ;
121
- for ( new_pos, c) in text[ pos..] . char_indices ( ) {
122
- if !c. is_whitespace ( ) {
123
- if c == '>' {
124
- r. end = range. start + new_pos + 1 ;
125
- found = true ;
126
- }
127
- break ;
128
- }
129
- }
130
- if !found {
131
- break ;
121
+ let mut found = false ;
122
+ for ( new_pos, c) in text[ pos..] . char_indices ( ) {
123
+ if !c. is_whitespace ( ) {
124
+ if c == '>' {
125
+ r. end = range. start + new_pos + 1 ;
126
+ found = true ;
132
127
}
128
+ break ;
133
129
}
134
- drop_tag ( tags , tag_name , r , f ) ;
135
- } else {
136
- tags . push ( ( tag_name , r ) ) ;
130
+ }
131
+ if !found {
132
+ break ;
137
133
}
138
134
}
139
- break ;
135
+ drop_tag ( tags, tag_name, r, f) ;
136
+ } else {
137
+ tags. push ( ( tag_name, r) ) ;
140
138
}
141
- iter. next ( ) ;
142
139
}
140
+ break ;
141
+ }
142
+ iter. next ( ) ;
143
+ }
144
+ }
145
+
146
+ fn extract_tags (
147
+ tags : & mut Vec < ( String , Range < usize > ) > ,
148
+ text : & str ,
149
+ range : Range < usize > ,
150
+ f : & impl Fn ( & str , & Range < usize > ) ,
151
+ ) {
152
+ let mut iter = text. char_indices ( ) . peekable ( ) ;
153
+
154
+ while let Some ( ( start_pos, c) ) = iter. next ( ) {
155
+ if c == '<' {
156
+ extract_html_tag ( tags, text, & range, start_pos, & mut iter, f) ;
143
157
}
144
158
}
145
159
}
@@ -172,7 +186,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
172
186
173
187
for ( event, range) in p {
174
188
match event {
175
- Event :: Html ( text) => extract_tag ( & mut tags, & text, range, & report_diag) ,
189
+ Event :: Html ( text) => extract_tags ( & mut tags, & text, range, & report_diag) ,
176
190
_ => { }
177
191
}
178
192
}
0 commit comments