@@ -8,6 +8,7 @@ use rustc_errors::Applicability;
8
8
use rustc_lexer:: unescape:: { self , EscapeError } ;
9
9
use rustc_parse:: parser;
10
10
use syntax:: ast:: * ;
11
+ use syntax:: symbol:: Symbol ;
11
12
use syntax:: token;
12
13
use syntax:: tokenstream:: TokenStream ;
13
14
use syntax_pos:: { BytePos , Span } ;
@@ -190,7 +191,7 @@ impl EarlyLintPass for Write {
190
191
if mac. path == sym ! ( println) {
191
192
span_lint ( cx, PRINT_STDOUT , mac. span , "use of `println!`" ) ;
192
193
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 ( "" ) {
194
195
span_lint_and_sugg (
195
196
cx,
196
197
PRINTLN_EMPTY_STRING ,
@@ -205,7 +206,7 @@ impl EarlyLintPass for Write {
205
206
} else if mac. path == sym ! ( print) {
206
207
span_lint ( cx, PRINT_STDOUT , mac. span , "use of `print!`" ) ;
207
208
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) {
209
210
span_lint_and_then (
210
211
cx,
211
212
PRINT_WITH_NEWLINE ,
@@ -216,7 +217,7 @@ impl EarlyLintPass for Write {
216
217
"use `println!` instead" ,
217
218
vec ! [
218
219
( mac. path. span, String :: from( "println" ) ) ,
219
- ( fmt_str . newline_span( ) , String :: new( ) ) ,
220
+ ( newline_span( & fmt_str ) , String :: new( ) ) ,
220
221
] ,
221
222
Applicability :: MachineApplicable ,
222
223
) ;
@@ -226,7 +227,7 @@ impl EarlyLintPass for Write {
226
227
}
227
228
} else if mac. path == sym ! ( write) {
228
229
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) {
230
231
span_lint_and_then (
231
232
cx,
232
233
WRITE_WITH_NEWLINE ,
@@ -237,7 +238,7 @@ impl EarlyLintPass for Write {
237
238
"use `writeln!()` instead" ,
238
239
vec ! [
239
240
( mac. path. span, String :: from( "writeln" ) ) ,
240
- ( fmt_str . newline_span( ) , String :: new( ) ) ,
241
+ ( newline_span( & fmt_str ) , String :: new( ) ) ,
241
242
] ,
242
243
Applicability :: MachineApplicable ,
243
244
) ;
@@ -247,7 +248,7 @@ impl EarlyLintPass for Write {
247
248
}
248
249
} else if mac. path == sym ! ( writeln) {
249
250
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 ( "" ) {
251
252
let mut applicability = Applicability :: MachineApplicable ;
252
253
let suggestion = expr. map_or_else (
253
254
move || {
@@ -272,37 +273,27 @@ impl EarlyLintPass for Write {
272
273
}
273
274
}
274
275
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 ( ) ;
289
281
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 ( ) ) ,
302
286
} ;
303
287
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)
306
297
}
307
298
308
299
/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
@@ -325,7 +316,7 @@ impl FmtStr {
325
316
/// (Some("string to write: {}"), Some(buf))
326
317
/// ```
327
318
#[ 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 > ) {
329
320
use fmt_macros:: * ;
330
321
let tts = tts. clone ( ) ;
331
322
@@ -342,12 +333,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
342
333
}
343
334
}
344
335
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,
347
338
Err ( _) => return ( None , expr) ,
348
339
} ;
349
- let fmtspan = parser. prev_span ;
350
- let tmp = fmtstr. clone ( ) ;
340
+ let tmp = fmtstr. symbol . as_str ( ) ;
351
341
let mut args = vec ! [ ] ;
352
342
let mut fmt_parser = Parser :: new ( & tmp, None , Vec :: new ( ) , false ) ;
353
343
while let Some ( piece) = fmt_parser. next ( ) {
@@ -377,26 +367,12 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
377
367
ty_span : None ,
378
368
} ;
379
369
if !parser. eat ( & token:: Comma ) {
380
- return (
381
- Some ( FmtStr {
382
- contents : fmtstr,
383
- style : fmtstyle,
384
- span : fmtspan,
385
- } ) ,
386
- expr,
387
- ) ;
370
+ return ( Some ( fmtstr) , expr) ;
388
371
}
389
372
let token_expr = if let Ok ( expr) = parser. parse_expr ( ) . map_err ( |mut err| err. cancel ( ) ) {
390
373
expr
391
374
} else {
392
- return (
393
- Some ( FmtStr {
394
- contents : fmtstr,
395
- style : fmtstyle,
396
- span : fmtspan,
397
- } ) ,
398
- None ,
399
- ) ;
375
+ return ( Some ( fmtstr) , None ) ;
400
376
} ;
401
377
match & token_expr. kind {
402
378
ExprKind :: Lit ( _) => {
@@ -448,11 +424,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
448
424
/// Checks if the format string contains a single newline that terminates it.
449
425
///
450
426
/// Literal and escaped newlines are both checked (only literal for raw strings).
451
- fn check_newlines ( contents : & str , style : StrStyle ) -> bool {
427
+ fn check_newlines ( fmtstr : & StrLit ) -> bool {
452
428
let mut has_internal_newline = false ;
453
429
let mut last_was_cr = false ;
454
430
let mut should_lint = false ;
455
431
432
+ let contents = & fmtstr. symbol . as_str ( ) ;
433
+
456
434
let mut cb = |r : Range < usize > , c : Result < char , EscapeError > | {
457
435
let c = c. unwrap ( ) ;
458
436
@@ -466,7 +444,7 @@ fn check_newlines(contents: &str, style: StrStyle) -> bool {
466
444
}
467
445
} ;
468
446
469
- match style {
447
+ match fmtstr . style {
470
448
StrStyle :: Cooked => unescape:: unescape_str ( contents, & mut cb) ,
471
449
StrStyle :: Raw ( _) => unescape:: unescape_raw_str ( contents, & mut cb) ,
472
450
}
0 commit comments