1
+ use crate :: utils:: { snippet, span_lint, span_lint_and_sugg} ;
1
2
use rustc:: lint:: { EarlyContext , EarlyLintPass , LintArray , LintPass } ;
2
3
use rustc:: { declare_tool_lint, lint_array} ;
4
+ use std:: borrow:: Cow ;
3
5
use syntax:: ast:: * ;
6
+ use syntax:: parse:: { parser, token} ;
4
7
use syntax:: tokenstream:: { ThinTokenStream , TokenStream } ;
5
- use syntax:: parse:: { token, parser} ;
6
- use std:: borrow:: Cow ;
7
- use crate :: utils:: { span_lint, span_lint_and_sugg, snippet} ;
8
8
9
9
/// **What it does:** This lint warns when you use `println!("")` to
10
10
/// print a newline.
@@ -195,25 +195,41 @@ impl EarlyLintPass for Pass {
195
195
} else if mac. node . path == "print" {
196
196
span_lint ( cx, PRINT_STDOUT , mac. span , "use of `print!`" ) ;
197
197
if let Some ( fmtstr) = check_tts ( cx, & mac. node . tts , false ) . 0 {
198
- if fmtstr. ends_with ( "\\ n" ) && !fmtstr. ends_with ( "\\ n\\ n" ) {
199
- span_lint ( cx, PRINT_WITH_NEWLINE , mac. span ,
200
- "using `print!()` with a format string that ends in a \
201
- single newline, consider using `println!()` instead") ;
198
+ if fmtstr. ends_with ( "\\ n" ) &&
199
+ // don't warn about strings with several `\n`s (#3126)
200
+ fmtstr. matches ( "\\ n" ) . count ( ) == 1
201
+ {
202
+ span_lint (
203
+ cx,
204
+ PRINT_WITH_NEWLINE ,
205
+ mac. span ,
206
+ "using `print!()` with a format string that ends in a \
207
+ single newline, consider using `println!()` instead",
208
+ ) ;
202
209
}
203
210
}
204
211
} else if mac. node . path == "write" {
205
212
if let Some ( fmtstr) = check_tts ( cx, & mac. node . tts , true ) . 0 {
206
- if fmtstr. ends_with ( "\\ n" ) && !fmtstr. ends_with ( "\\ n\\ n" ) {
207
- span_lint ( cx, WRITE_WITH_NEWLINE , mac. span ,
208
- "using `write!()` with a format string that ends in a \
209
- single newline, consider using `writeln!()` instead") ;
213
+ if fmtstr. ends_with ( "\\ n" ) &&
214
+ // don't warn about strings with several `\n`s (#3126)
215
+ fmtstr. matches ( "\\ n" ) . count ( ) == 1
216
+ {
217
+ span_lint (
218
+ cx,
219
+ WRITE_WITH_NEWLINE ,
220
+ mac. span ,
221
+ "using `write!()` with a format string that ends in a \
222
+ single newline, consider using `writeln!()` instead",
223
+ ) ;
210
224
}
211
225
}
212
226
} else if mac. node . path == "writeln" {
213
227
let check_tts = check_tts ( cx, & mac. node . tts , true ) ;
214
228
if let Some ( fmtstr) = check_tts. 0 {
215
229
if fmtstr == "" {
216
- let suggestion = check_tts. 1 . map_or ( Cow :: Borrowed ( "v" ) , |expr| snippet ( cx, expr. span , "v" ) ) ;
230
+ let suggestion = check_tts
231
+ . 1
232
+ . map_or ( Cow :: Borrowed ( "v" ) , |expr| snippet ( cx, expr. span , "v" ) ) ;
217
233
218
234
span_lint_and_sugg (
219
235
cx,
@@ -231,13 +247,7 @@ impl EarlyLintPass for Pass {
231
247
232
248
fn check_tts < ' a > ( cx : & EarlyContext < ' a > , tts : & ThinTokenStream , is_write : bool ) -> ( Option < String > , Option < Expr > ) {
233
249
let tts = TokenStream :: from ( tts. clone ( ) ) ;
234
- let mut parser = parser:: Parser :: new (
235
- & cx. sess . parse_sess ,
236
- tts,
237
- None ,
238
- false ,
239
- false ,
240
- ) ;
250
+ let mut parser = parser:: Parser :: new ( & cx. sess . parse_sess , tts, None , false , false ) ;
241
251
let mut expr: Option < Expr > = None ;
242
252
if is_write {
243
253
expr = match parser. parse_expr ( ) . map_err ( |mut err| err. cancel ( ) ) {
@@ -270,11 +280,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
270
280
args. push ( arg) ;
271
281
}
272
282
}
273
- let lint = if is_write {
274
- WRITE_LITERAL
275
- } else {
276
- PRINT_LITERAL
277
- } ;
283
+ let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL } ;
278
284
let mut idx = 0 ;
279
285
loop {
280
286
if !parser. eat ( & token:: Comma ) {
@@ -299,9 +305,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
299
305
let mut seen = false ;
300
306
for arg in & args {
301
307
match arg. position {
302
- | ArgumentImplicitlyIs ( n)
303
- | ArgumentIs ( n)
304
- => if n == idx {
308
+ ArgumentImplicitlyIs ( n) | ArgumentIs ( n) => if n == idx {
305
309
all_simple &= arg. format == SIMPLE ;
306
310
seen = true ;
307
311
} ,
@@ -320,9 +324,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
320
324
let mut seen = false ;
321
325
for arg in & args {
322
326
match arg. position {
323
- | ArgumentImplicitlyIs ( _)
324
- | ArgumentIs ( _)
325
- => { } ,
327
+ ArgumentImplicitlyIs ( _) | ArgumentIs ( _) => { } ,
326
328
ArgumentNamed ( name) => if * p == name {
327
329
seen = true ;
328
330
all_simple &= arg. format == SIMPLE ;
0 commit comments