Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions clippy_lints/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,7 @@ impl EarlyLintPass for Pass {
} else if mac.node.path == "print" {
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
if fmtstr.ends_with("\\n") &&
// don't warn about strings with several `\n`s (#3126)
fmtstr.matches("\\n").count() == 1
{
if check_newlines(&fmtstr) {
span_lint(
cx,
PRINT_WITH_NEWLINE,
Expand All @@ -221,10 +218,7 @@ impl EarlyLintPass for Pass {
}
} else if mac.node.path == "write" {
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 {
if fmtstr.ends_with("\\n") &&
// don't warn about strings with several `\n`s (#3126)
fmtstr.matches("\\n").count() == 1
{
if check_newlines(&fmtstr) {
span_lint(
cx,
WRITE_WITH_NEWLINE,
Expand Down Expand Up @@ -375,3 +369,29 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -
}
}
}

// Checks if `s` constains a single newline that terminates it
fn check_newlines(s: &str) -> bool {
if s.len() < 2 {
return false;
}

let bytes = s.as_bytes();
if bytes[bytes.len() - 2] != b'\\' || bytes[bytes.len() - 1] != b'n' {
return false;
}

let mut escaping = false;
for (index, &byte) in bytes.iter().enumerate() {
if escaping {
if byte == b'n' {
return index == bytes.len() - 1;
}
escaping = false;
} else if byte == b'\\' {
escaping = true;
}
}

false
}
5 changes: 5 additions & 0 deletions tests/ui/write_with_newline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ fn main() {
write!(&mut v, "Hello {} {}\n\n", "world", "#2");
writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
writeln!(&mut v, "\nbla\n\n"); // #3126

// Escaping
write!(&mut v, "\\n"); // #3514
write!(&mut v, "\\\n");
write!(&mut v, "\\\\n");
}
8 changes: 7 additions & 1 deletion tests/ui/write_with_newline.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,11 @@ error: using `write!()` with a format string that ends in a single newline, cons
22 | write!(&mut v, "{}/n", 1265);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors
error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead
--> $DIR/write_with_newline.rs:41:5
|
41 | write!(&mut v, "//n");
| ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 5 previous errors