@@ -81,94 +81,105 @@ impl EarlyLintPass for RawStrings {
8181 && !in_external_macro ( cx. sess ( ) , expr. span )
8282 && expr. span . check_source_text ( cx, |src| src. starts_with ( prefix) )
8383 {
84- let str = lit. symbol . as_str ( ) ;
85- let descr = lit. kind . descr ( ) ;
86-
87- if !str. contains ( [ '\\' , '"' ] ) {
88- span_lint_and_then (
89- cx,
90- NEEDLESS_RAW_STRINGS ,
91- expr. span ,
92- "unnecessary raw string literal" ,
93- |diag| {
94- let ( start, end) = hash_spans ( expr. span , prefix. len ( ) , 0 , max) ;
95-
96- // BytePos: skip over the `b` in `br`, we checked the prefix appears in the source text
97- let r_pos = expr. span . lo ( ) + BytePos :: from_usize ( prefix. len ( ) - 1 ) ;
98- let start = start. with_lo ( r_pos) ;
99-
100- let mut remove = vec ! [ ( start, String :: new( ) ) ] ;
101- // avoid debug ICE from empty suggestions
102- if !end. is_empty ( ) {
103- remove. push ( ( end, String :: new ( ) ) ) ;
104- }
84+ self . check_raw_string ( cx, lit. symbol . as_str ( ) , expr. span , prefix, max, lit. kind . descr ( ) ) ;
85+ }
86+ }
87+ }
10588
106- diag. multipart_suggestion_verbose (
107- format ! ( "use a plain {descr} literal instead" ) ,
108- remove,
109- Applicability :: MachineApplicable ,
110- ) ;
111- } ,
112- ) ;
113- if !matches ! ( cx. get_lint_level( NEEDLESS_RAW_STRINGS ) , rustc_lint:: Allow ) {
114- return ;
115- }
89+ impl RawStrings {
90+ fn check_raw_string (
91+ & mut self ,
92+ cx : & EarlyContext < ' _ > ,
93+ str : & str ,
94+ lit_span : Span ,
95+ prefix : & str ,
96+ max : u8 ,
97+ descr : & str ,
98+ ) {
99+ if !str. contains ( [ '\\' , '"' ] ) {
100+ span_lint_and_then (
101+ cx,
102+ NEEDLESS_RAW_STRINGS ,
103+ lit_span,
104+ "unnecessary raw string literal" ,
105+ |diag| {
106+ let ( start, end) = hash_spans ( lit_span, prefix. len ( ) , 0 , max) ;
107+
108+ // BytePos: skip over the `b` in `br`, we checked the prefix appears in the source text
109+ let r_pos = lit_span. lo ( ) + BytePos :: from_usize ( prefix. len ( ) - 1 ) ;
110+ let start = start. with_lo ( r_pos) ;
111+
112+ let mut remove = vec ! [ ( start, String :: new( ) ) ] ;
113+ // avoid debug ICE from empty suggestions
114+ if !end. is_empty ( ) {
115+ remove. push ( ( end, String :: new ( ) ) ) ;
116+ }
117+
118+ diag. multipart_suggestion_verbose (
119+ format ! ( "use a plain {descr} literal instead" ) ,
120+ remove,
121+ Applicability :: MachineApplicable ,
122+ ) ;
123+ } ,
124+ ) ;
125+ if !matches ! ( cx. get_lint_level( NEEDLESS_RAW_STRINGS ) , rustc_lint:: Allow ) {
126+ return ;
116127 }
128+ }
117129
118- let mut req = {
119- let mut following_quote = false ;
120- let mut req = 0 ;
121- // `once` so a raw string ending in hashes is still checked
122- let num = str. as_bytes ( ) . iter ( ) . chain ( once ( & 0 ) ) . try_fold ( 0u8 , |acc, & b| {
123- match b {
124- b'"' if !following_quote => ( following_quote, req) = ( true , 1 ) ,
125- b'#' => req += u8:: from ( following_quote) ,
126- _ => {
127- if following_quote {
128- following_quote = false ;
129-
130- if req == max {
131- return ControlFlow :: Break ( req) ;
132- }
133-
134- return ControlFlow :: Continue ( acc. max ( req) ) ;
130+ let mut req = {
131+ let mut following_quote = false ;
132+ let mut req = 0 ;
133+ // `once` so a raw string ending in hashes is still checked
134+ let num = str. as_bytes ( ) . iter ( ) . chain ( once ( & 0 ) ) . try_fold ( 0u8 , |acc, & b| {
135+ match b {
136+ b'"' if !following_quote => ( following_quote, req) = ( true , 1 ) ,
137+ b'#' => req += u8:: from ( following_quote) ,
138+ _ => {
139+ if following_quote {
140+ following_quote = false ;
141+
142+ if req == max {
143+ return ControlFlow :: Break ( req) ;
135144 }
136- } ,
137- }
138-
139- ControlFlow :: Continue ( acc)
140- } ) ;
141145
142- match num {
143- ControlFlow :: Continue ( num) | ControlFlow :: Break ( num) => num,
144- }
145- } ;
146- if self . allow_one_hash_in_raw_strings {
147- req = req. max ( 1 ) ;
148- }
149- if req < max {
150- span_lint_and_then (
151- cx,
152- NEEDLESS_RAW_STRING_HASHES ,
153- expr. span ,
154- "unnecessary hashes around raw string literal" ,
155- |diag| {
156- let ( start, end) = hash_spans ( expr. span , prefix. len ( ) , req, max) ;
157-
158- let message = match max - req {
159- _ if req == 0 => format ! ( "remove all the hashes around the {descr} literal" ) ,
160- 1 => format ! ( "remove one hash from both sides of the {descr} literal" ) ,
161- n => format ! ( "remove {n} hashes from both sides of the {descr} literal" ) ,
162- } ;
163-
164- diag. multipart_suggestion (
165- message,
166- vec ! [ ( start, String :: new( ) ) , ( end, String :: new( ) ) ] ,
167- Applicability :: MachineApplicable ,
168- ) ;
146+ return ControlFlow :: Continue ( acc. max ( req) ) ;
147+ }
169148 } ,
170- ) ;
149+ }
150+
151+ ControlFlow :: Continue ( acc)
152+ } ) ;
153+
154+ match num {
155+ ControlFlow :: Continue ( num) | ControlFlow :: Break ( num) => num,
171156 }
157+ } ;
158+ if self . allow_one_hash_in_raw_strings {
159+ req = req. max ( 1 ) ;
160+ }
161+ if req < max {
162+ span_lint_and_then (
163+ cx,
164+ NEEDLESS_RAW_STRING_HASHES ,
165+ lit_span,
166+ "unnecessary hashes around raw string literal" ,
167+ |diag| {
168+ let ( start, end) = hash_spans ( lit_span, prefix. len ( ) , req, max) ;
169+
170+ let message = match max - req {
171+ _ if req == 0 => format ! ( "remove all the hashes around the {descr} literal" ) ,
172+ 1 => format ! ( "remove one hash from both sides of the {descr} literal" ) ,
173+ n => format ! ( "remove {n} hashes from both sides of the {descr} literal" ) ,
174+ } ;
175+
176+ diag. multipart_suggestion (
177+ message,
178+ vec ! [ ( start, String :: new( ) ) , ( end, String :: new( ) ) ] ,
179+ Applicability :: MachineApplicable ,
180+ ) ;
181+ } ,
182+ ) ;
172183 }
173184 }
174185}
0 commit comments