@@ -249,6 +249,8 @@ struct TagParser {
249249 tag_name : String ,
250250 tag_start_pos : usize ,
251251 is_closing : bool ,
252+ /// `true` if we are within a tag, but not within its name.
253+ in_attrs : bool ,
252254}
253255
254256impl TagParser {
@@ -258,6 +260,7 @@ impl TagParser {
258260 tag_name : String :: with_capacity ( 8 ) ,
259261 is_closing : false ,
260262 tag_start_pos : 0 ,
263+ in_attrs : false ,
261264 }
262265 }
263266
@@ -322,7 +325,7 @@ impl TagParser {
322325 ) {
323326 let mut prev_pos = start_pos;
324327
325- loop {
328+ ' outer_loop : loop {
326329 let ( pos, c) = match iter. peek ( ) {
327330 Some ( ( pos, c) ) => ( * pos, * c) ,
328331 // In case we reached the of the doc comment, we want to check that it's an
@@ -334,10 +337,11 @@ impl TagParser {
334337 // Checking if this is a closing tag (like `</a>` for `<a>`).
335338 if c == '/' && self . tag_name . is_empty ( ) {
336339 self . is_closing = true ;
337- } else if is_valid_for_html_tag_name ( c, self . tag_name . is_empty ( ) ) {
340+ } else if ! self . in_attrs && is_valid_for_html_tag_name ( c, self . tag_name . is_empty ( ) ) {
338341 self . tag_name . push ( c) ;
339342 } else {
340343 if !self . tag_name . is_empty ( ) {
344+ self . in_attrs = true ;
341345 let mut r = Range { start : range. start + start_pos, end : range. start + pos } ;
342346 if c == '>' {
343347 // In case we have a tag without attribute, we can consider the span to
@@ -365,7 +369,7 @@ impl TagParser {
365369 }
366370 }
367371 if !found {
368- break ;
372+ break ' outer_loop ;
369373 }
370374 }
371375 self . drop_tag ( r, dox, f) ;
@@ -375,34 +379,42 @@ impl TagParser {
375379 if c != '>' {
376380 let mut quote = None ;
377381 let mut after_eq = false ;
378- for ( i, c) in text[ pos..] . char_indices ( ) {
379- if !c. is_whitespace ( ) {
380- if let Some ( q) = quote {
381- if c == q {
382- quote = None ;
383- quote_pos = None ;
384- after_eq = false ;
385- }
386- } else if c == '>' {
387- break ;
388- } else if c == '<' {
389- self . handle_lt_in_tag ( range. clone ( ) , pos + i, f) ;
390- } else if c == '/' && !after_eq {
391- is_self_closing = true ;
392- } else {
393- if is_self_closing {
394- is_self_closing = false ;
395- }
396- if ( c == '"' || c == '\'' ) && after_eq {
397- quote = Some ( c) ;
398- quote_pos = Some ( pos + i) ;
399- } else if c == '=' {
400- after_eq = true ;
382+ ' parse_til_gt: {
383+ for ( i, c) in text[ pos..] . char_indices ( ) {
384+ if !c. is_whitespace ( ) {
385+ if let Some ( q) = quote {
386+ if c == q {
387+ quote = None ;
388+ quote_pos = None ;
389+ after_eq = false ;
390+ }
391+ } else if c == '>' {
392+ // fall through and call `tag_parsed`.
393+ break ' parse_til_gt;
394+ } else if c == '<' {
395+ self . handle_lt_in_tag ( range. clone ( ) , pos + i, f) ;
396+ } else if c == '/' && !after_eq {
397+ is_self_closing = true ;
398+ } else {
399+ if is_self_closing {
400+ is_self_closing = false ;
401+ }
402+ if ( c == '"' || c == '\'' ) && after_eq {
403+ quote = Some ( c) ;
404+ quote_pos = Some ( pos + i) ;
405+ } else if c == '=' {
406+ after_eq = true ;
407+ }
401408 }
409+ } else if quote. is_none ( ) {
410+ after_eq = false ;
402411 }
403- } else if quote. is_none ( ) {
404- after_eq = false ;
405412 }
413+ // if we've run out of text but still haven't found a `>`,
414+ // break out of the outer loop to skip over `tag_parsed`.
415+ // this allows us to either find the `>` in a later event
416+ // or emit a lint about it being missing.
417+ break ' outer_loop;
406418 }
407419 }
408420 if let Some ( quote_pos) = quote_pos {
@@ -423,7 +435,7 @@ impl TagParser {
423435 if !valid {
424436 f ( format ! ( "invalid self-closing HTML tag `{}`" , self . tag_name) , & r, false ) ;
425437 }
426- } else {
438+ } else if ! self . tag_name . is_empty ( ) {
427439 self . tags . push ( ( std:: mem:: take ( & mut self . tag_name ) , r) ) ;
428440 }
429441 }
@@ -439,6 +451,7 @@ impl TagParser {
439451 fn tag_parsed ( & mut self ) {
440452 self . tag_name . clear ( ) ;
441453 self . is_closing = false ;
454+ self . in_attrs = false ;
442455 }
443456
444457 fn extract_tags (
0 commit comments