@@ -25,91 +25,85 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
2525 Some ( sp) => sp,
2626 None => item. attr_span ( tcx) ,
2727 } ;
28- tcx. struct_span_lint_hir (
29- crate :: lint :: INVALID_HTML_TAGS ,
30- hir_id ,
31- sp ,
32- msg . to_string ( ) ,
33- |lint| {
34- use rustc_lint_defs :: Applicability ;
35- // If a tag looks like `<this>`, it might actually be a generic.
36- // We don't try to detect stuff `<like, this>` because that's not valid HTML,
37- // and we don't try to detect stuff `<like this>` because that's not valid Rust.
38- let mut generics_end = range . end ;
39- if let Some ( Some ( mut generics_start ) ) = ( is_open_tag
40- && dox[ ..generics_end ] . ends_with ( '>' ) )
41- . then ( || extract_path_backwards ( & dox , range . start ) )
28+ tcx. struct_span_lint_hir ( crate :: lint :: INVALID_HTML_TAGS , hir_id , sp , msg , |lint| {
29+ use rustc_lint_defs :: Applicability ;
30+ // If a tag looks like `<this>`, it might actually be a generic.
31+ // We don't try to detect stuff `<like, this>` because that's not valid HTML ,
32+ // and we don't try to detect stuff `<like this>` because that's not valid Rust.
33+ let mut generics_end = range . end ;
34+ if let Some ( Some ( mut generics_start ) ) = ( is_open_tag
35+ && dox [ ..generics_end ] . ends_with ( '>' ) )
36+ . then ( || extract_path_backwards ( & dox , range . start ) )
37+ {
38+ while generics_start != 0
39+ && generics_end < dox . len ( )
40+ && dox. as_bytes ( ) [ generics_start - 1 ] == b'<'
41+ && dox . as_bytes ( ) [ generics_end ] == b'>'
4242 {
43- while generics_start != 0
44- && generics_end < dox. len ( )
45- && dox. as_bytes ( ) [ generics_start - 1 ] == b'<'
46- && dox. as_bytes ( ) [ generics_end] == b'>'
47- {
48- generics_end += 1 ;
49- generics_start -= 1 ;
50- if let Some ( new_start) = extract_path_backwards ( & dox, generics_start) {
51- generics_start = new_start;
52- }
53- if let Some ( new_end) = extract_path_forward ( & dox, generics_end) {
54- generics_end = new_end;
55- }
43+ generics_end += 1 ;
44+ generics_start -= 1 ;
45+ if let Some ( new_start) = extract_path_backwards ( & dox, generics_start) {
46+ generics_start = new_start;
5647 }
5748 if let Some ( new_end) = extract_path_forward ( & dox, generics_end) {
5849 generics_end = new_end;
5950 }
60- let generics_sp = match source_span_for_markdown_range (
61- tcx,
62- & dox,
63- & ( generics_start..generics_end) ,
64- & item. attrs . doc_strings ,
65- ) {
66- Some ( sp) => sp,
67- None => item. attr_span ( tcx) ,
68- } ;
69- // Sometimes, we only extract part of a path. For example, consider this:
70- //
71- // <[u32] as IntoIter<u32>>::Item
72- // ^^^^^ unclosed HTML tag `u32`
73- //
74- // We don't have any code for parsing fully-qualified trait paths.
75- // In theory, we could add it, but doing it correctly would require
76- // parsing the entire path grammar, which is problematic because of
77- // overlap between the path grammar and Markdown.
78- //
79- // The example above shows that ambiguity. Is `[u32]` intended to be an
80- // intra-doc link to the u32 primitive, or is it intended to be a slice?
81- //
82- // If the below conditional were removed, we would suggest this, which is
83- // not what the user probably wants.
84- //
85- // <[u32] as `IntoIter<u32>`>::Item
86- //
87- // We know that the user actually wants to wrap the whole thing in a code
88- // block, but the only reason we know that is because `u32` does not, in
89- // fact, implement IntoIter. If the example looks like this:
90- //
91- // <[Vec<i32>] as IntoIter<i32>::Item
92- //
93- // The ideal fix would be significantly different.
94- if ( generics_start > 0 && dox. as_bytes ( ) [ generics_start - 1 ] == b'<' )
95- || ( generics_end < dox. len ( ) && dox. as_bytes ( ) [ generics_end] == b'>' )
96- {
97- return lint;
98- }
99- // multipart form is chosen here because ``Vec<i32>`` would be confusing.
100- lint. multipart_suggestion (
101- "try marking as source code" ,
102- vec ! [
103- ( generics_sp. shrink_to_lo( ) , String :: from( "`" ) ) ,
104- ( generics_sp. shrink_to_hi( ) , String :: from( "`" ) ) ,
105- ] ,
106- Applicability :: MaybeIncorrect ,
107- ) ;
10851 }
52+ if let Some ( new_end) = extract_path_forward ( & dox, generics_end) {
53+ generics_end = new_end;
54+ }
55+ let generics_sp = match source_span_for_markdown_range (
56+ tcx,
57+ & dox,
58+ & ( generics_start..generics_end) ,
59+ & item. attrs . doc_strings ,
60+ ) {
61+ Some ( sp) => sp,
62+ None => item. attr_span ( tcx) ,
63+ } ;
64+ // Sometimes, we only extract part of a path. For example, consider this:
65+ //
66+ // <[u32] as IntoIter<u32>>::Item
67+ // ^^^^^ unclosed HTML tag `u32`
68+ //
69+ // We don't have any code for parsing fully-qualified trait paths.
70+ // In theory, we could add it, but doing it correctly would require
71+ // parsing the entire path grammar, which is problematic because of
72+ // overlap between the path grammar and Markdown.
73+ //
74+ // The example above shows that ambiguity. Is `[u32]` intended to be an
75+ // intra-doc link to the u32 primitive, or is it intended to be a slice?
76+ //
77+ // If the below conditional were removed, we would suggest this, which is
78+ // not what the user probably wants.
79+ //
80+ // <[u32] as `IntoIter<u32>`>::Item
81+ //
82+ // We know that the user actually wants to wrap the whole thing in a code
83+ // block, but the only reason we know that is because `u32` does not, in
84+ // fact, implement IntoIter. If the example looks like this:
85+ //
86+ // <[Vec<i32>] as IntoIter<i32>::Item
87+ //
88+ // The ideal fix would be significantly different.
89+ if ( generics_start > 0 && dox. as_bytes ( ) [ generics_start - 1 ] == b'<' )
90+ || ( generics_end < dox. len ( ) && dox. as_bytes ( ) [ generics_end] == b'>' )
91+ {
92+ return lint;
93+ }
94+ // multipart form is chosen here because ``Vec<i32>`` would be confusing.
95+ lint. multipart_suggestion (
96+ "try marking as source code" ,
97+ vec ! [
98+ ( generics_sp. shrink_to_lo( ) , String :: from( "`" ) ) ,
99+ ( generics_sp. shrink_to_hi( ) , String :: from( "`" ) ) ,
100+ ] ,
101+ Applicability :: MaybeIncorrect ,
102+ ) ;
103+ }
109104
110- lint
111- } ,
112- ) ;
105+ lint
106+ } ) ;
113107 } ;
114108
115109 let mut tags = Vec :: new ( ) ;
0 commit comments