Skip to content

Commit 8af6927

Browse files
authored
Merge pull request #3138 from matthiaskrgr/3126__no_warn_multi_newline
print_with_newline / write_with_newline: don't warn about string with several `\n`s in them.
2 parents 3262f92 + a0f56ed commit 8af6927

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

clippy_lints/src/write.rs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use crate::utils::{snippet, span_lint, span_lint_and_sugg};
12
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
23
use rustc::{declare_tool_lint, lint_array};
4+
use std::borrow::Cow;
35
use syntax::ast::*;
6+
use syntax::parse::{parser, token};
47
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};
88

99
/// **What it does:** This lint warns when you use `println!("")` to
1010
/// print a newline.
@@ -195,25 +195,41 @@ impl EarlyLintPass for Pass {
195195
} else if mac.node.path == "print" {
196196
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
197197
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+
);
202209
}
203210
}
204211
} else if mac.node.path == "write" {
205212
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+
);
210224
}
211225
}
212226
} else if mac.node.path == "writeln" {
213227
let check_tts = check_tts(cx, &mac.node.tts, true);
214228
if let Some(fmtstr) = check_tts.0 {
215229
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"));
217233

218234
span_lint_and_sugg(
219235
cx,
@@ -231,13 +247,7 @@ impl EarlyLintPass for Pass {
231247

232248
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
233249
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);
241251
let mut expr: Option<Expr> = None;
242252
if is_write {
243253
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) -
270280
args.push(arg);
271281
}
272282
}
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 };
278284
let mut idx = 0;
279285
loop {
280286
if !parser.eat(&token::Comma) {
@@ -299,9 +305,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
299305
let mut seen = false;
300306
for arg in &args {
301307
match arg.position {
302-
| ArgumentImplicitlyIs(n)
303-
| ArgumentIs(n)
304-
=> if n == idx {
308+
ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx {
305309
all_simple &= arg.format == SIMPLE;
306310
seen = true;
307311
},
@@ -320,9 +324,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
320324
let mut seen = false;
321325
for arg in &args {
322326
match arg.position {
323-
| ArgumentImplicitlyIs(_)
324-
| ArgumentIs(_)
325-
=> {},
327+
ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
326328
ArgumentNamed(name) => if *p == name {
327329
seen = true;
328330
all_simple &= arg.format == SIMPLE;

tests/ui/print_with_newline.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ fn main() {
2121
print!("\n\n");
2222
print!("like eof\n\n");
2323
print!("Hello {} {}\n\n", "world", "#2");
24+
println!("\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
25+
println!("\nbla\n\n"); // #3126
2426
}

tests/ui/write_with_newline.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ fn main() {
2626
write!(&mut v, "\n\n");
2727
write!(&mut v, "like eof\n\n");
2828
write!(&mut v, "Hello {} {}\n\n", "world", "#2");
29+
writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
30+
writeln!(&mut v, "\nbla\n\n"); // #3126
2931
}

0 commit comments

Comments
 (0)