@@ -8,6 +8,7 @@ use rustc_errors::Applicability;
88use rustc_lexer:: unescape:: { self , EscapeError } ;
99use rustc_parse:: parser;
1010use syntax:: ast:: * ;
11+ use syntax:: symbol:: Symbol ;
1112use syntax:: token;
1213use syntax:: tokenstream:: TokenStream ;
1314use syntax_pos:: { BytePos , Span } ;
@@ -190,7 +191,7 @@ impl EarlyLintPass for Write {
190191 if mac. path == sym ! ( println) {
191192 span_lint ( cx, PRINT_STDOUT , mac. span , "use of `println!`" ) ;
192193 if let ( Some ( fmt_str) , _) = check_tts ( cx, & mac. tts , false ) {
193- if fmt_str. contents . is_empty ( ) {
194+ if fmt_str. symbol == Symbol :: intern ( "" ) {
194195 span_lint_and_sugg (
195196 cx,
196197 PRINTLN_EMPTY_STRING ,
@@ -205,7 +206,7 @@ impl EarlyLintPass for Write {
205206 } else if mac. path == sym ! ( print) {
206207 span_lint ( cx, PRINT_STDOUT , mac. span , "use of `print!`" ) ;
207208 if let ( Some ( fmt_str) , _) = check_tts ( cx, & mac. tts , false ) {
208- if check_newlines ( & fmt_str. contents , fmt_str . style ) {
209+ if check_newlines ( & fmt_str) {
209210 span_lint_and_then (
210211 cx,
211212 PRINT_WITH_NEWLINE ,
@@ -216,7 +217,7 @@ impl EarlyLintPass for Write {
216217 "use `println!` instead" ,
217218 vec ! [
218219 ( mac. path. span, String :: from( "println" ) ) ,
219- ( fmt_str . newline_span( ) , String :: new( ) ) ,
220+ ( newline_span( & fmt_str ) , String :: new( ) ) ,
220221 ] ,
221222 Applicability :: MachineApplicable ,
222223 ) ;
@@ -226,7 +227,7 @@ impl EarlyLintPass for Write {
226227 }
227228 } else if mac. path == sym ! ( write) {
228229 if let ( Some ( fmt_str) , _) = check_tts ( cx, & mac. tts , true ) {
229- if check_newlines ( & fmt_str. contents , fmt_str . style ) {
230+ if check_newlines ( & fmt_str) {
230231 span_lint_and_then (
231232 cx,
232233 WRITE_WITH_NEWLINE ,
@@ -237,7 +238,7 @@ impl EarlyLintPass for Write {
237238 "use `writeln!()` instead" ,
238239 vec ! [
239240 ( mac. path. span, String :: from( "writeln" ) ) ,
240- ( fmt_str . newline_span( ) , String :: new( ) ) ,
241+ ( newline_span( & fmt_str ) , String :: new( ) ) ,
241242 ] ,
242243 Applicability :: MachineApplicable ,
243244 ) ;
@@ -247,7 +248,7 @@ impl EarlyLintPass for Write {
247248 }
248249 } else if mac. path == sym ! ( writeln) {
249250 if let ( Some ( fmt_str) , expr) = check_tts ( cx, & mac. tts , true ) {
250- if fmt_str. contents . is_empty ( ) {
251+ if fmt_str. symbol == Symbol :: intern ( "" ) {
251252 let mut applicability = Applicability :: MachineApplicable ;
252253 let suggestion = expr. map_or_else (
253254 move || {
@@ -272,37 +273,27 @@ impl EarlyLintPass for Write {
272273 }
273274}
274275
275- /// The arguments of a `print[ln]!` or `write[ln]!` invocation.
276- struct FmtStr {
277- /// The contents of the format string (inside the quotes).
278- contents : String ,
279- style : StrStyle ,
280- /// The span of the format string, including quotes, the raw marker, and any raw hashes.
281- span : Span ,
282- }
283-
284- impl FmtStr {
285- /// Given a format string that ends in a newline and its span, calculates the span of the
286- /// newline.
287- fn newline_span ( & self ) -> Span {
288- let sp = self . span ;
276+ /// Given a format string that ends in a newline and its span, calculates the span of the
277+ /// newline.
278+ fn newline_span ( fmtstr : & StrLit ) -> Span {
279+ let sp = fmtstr. span ;
280+ let contents = & fmtstr. symbol . as_str ( ) ;
289281
290- let newline_sp_hi = sp. hi ( )
291- - match self . style {
292- StrStyle :: Cooked => BytePos ( 1 ) ,
293- StrStyle :: Raw ( hashes) => BytePos ( ( 1 + hashes) . into ( ) ) ,
294- } ;
295-
296- let newline_sp_len = if self . contents . ends_with ( '\n' ) {
297- BytePos ( 1 )
298- } else if self . contents . ends_with ( r"\n" ) {
299- BytePos ( 2 )
300- } else {
301- panic ! ( "expected format string to contain a newline" ) ;
282+ let newline_sp_hi = sp. hi ( )
283+ - match fmtstr. style {
284+ StrStyle :: Cooked => BytePos ( 1 ) ,
285+ StrStyle :: Raw ( hashes) => BytePos ( ( 1 + hashes) . into ( ) ) ,
302286 } ;
303287
304- sp. with_lo ( newline_sp_hi - newline_sp_len) . with_hi ( newline_sp_hi)
305- }
288+ let newline_sp_len = if contents. ends_with ( '\n' ) {
289+ BytePos ( 1 )
290+ } else if contents. ends_with ( r"\n" ) {
291+ BytePos ( 2 )
292+ } else {
293+ panic ! ( "expected format string to contain a newline" ) ;
294+ } ;
295+
296+ sp. with_lo ( newline_sp_hi - newline_sp_len) . with_hi ( newline_sp_hi)
306297}
307298
308299/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
@@ -325,7 +316,7 @@ impl FmtStr {
325316/// (Some("string to write: {}"), Some(buf))
326317/// ```
327318#[ allow( clippy:: too_many_lines) ]
328- fn check_tts < ' a > ( cx : & EarlyContext < ' a > , tts : & TokenStream , is_write : bool ) -> ( Option < FmtStr > , Option < Expr > ) {
319+ fn check_tts < ' a > ( cx : & EarlyContext < ' a > , tts : & TokenStream , is_write : bool ) -> ( Option < StrLit > , Option < Expr > ) {
329320 use fmt_macros:: * ;
330321 let tts = tts. clone ( ) ;
331322
@@ -342,12 +333,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
342333 }
343334 }
344335
345- let ( fmtstr, fmtstyle ) = match parser. parse_str ( ) . map_err ( | mut err| err . cancel ( ) ) {
346- Ok ( ( fmtstr, fmtstyle ) ) => ( fmtstr. to_string ( ) , fmtstyle ) ,
336+ let fmtstr = match parser. parse_str_lit ( ) {
337+ Ok ( fmtstr) => fmtstr,
347338 Err ( _) => return ( None , expr) ,
348339 } ;
349- let fmtspan = parser. prev_span ;
350- let tmp = fmtstr. clone ( ) ;
340+ let tmp = fmtstr. symbol . as_str ( ) ;
351341 let mut args = vec ! [ ] ;
352342 let mut fmt_parser = Parser :: new ( & tmp, None , Vec :: new ( ) , false ) ;
353343 while let Some ( piece) = fmt_parser. next ( ) {
@@ -378,23 +368,15 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
378368 } ;
379369 if !parser. eat ( & token:: Comma ) {
380370 return (
381- Some ( FmtStr {
382- contents : fmtstr,
383- style : fmtstyle,
384- span : fmtspan,
385- } ) ,
371+ Some ( fmtstr) ,
386372 expr,
387373 ) ;
388374 }
389375 let token_expr = if let Ok ( expr) = parser. parse_expr ( ) . map_err ( |mut err| err. cancel ( ) ) {
390376 expr
391377 } else {
392378 return (
393- Some ( FmtStr {
394- contents : fmtstr,
395- style : fmtstyle,
396- span : fmtspan,
397- } ) ,
379+ Some ( fmtstr) ,
398380 None ,
399381 ) ;
400382 } ;
@@ -448,11 +430,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
448430/// Checks if the format string contains a single newline that terminates it.
449431///
450432/// Literal and escaped newlines are both checked (only literal for raw strings).
451- fn check_newlines ( contents : & str , style : StrStyle ) -> bool {
433+ fn check_newlines ( fmtstr : & StrLit ) -> bool {
452434 let mut has_internal_newline = false ;
453435 let mut last_was_cr = false ;
454436 let mut should_lint = false ;
455437
438+ let contents = & fmtstr. symbol . as_str ( ) ;
439+
456440 let mut cb = |r : Range < usize > , c : Result < char , EscapeError > | {
457441 let c = c. unwrap ( ) ;
458442
@@ -466,7 +450,7 @@ fn check_newlines(contents: &str, style: StrStyle) -> bool {
466450 }
467451 } ;
468452
469- match style {
453+ match fmtstr . style {
470454 StrStyle :: Cooked => unescape:: unescape_str ( contents, & mut cb) ,
471455 StrStyle :: Raw ( _) => unescape:: unescape_raw_str ( contents, & mut cb) ,
472456 }
0 commit comments