Auto merge of #3531 - mikerite:fix-3514, r=phansch

Fix write_with_newline escaping false positive

Fixes #3514
This commit is contained in:
bors 2018-12-14 08:42:09 +00:00
commit 17a9aff71a
3 changed files with 40 additions and 9 deletions

View file

@ -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,
@ -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,
@ -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
}

View file

@ -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");
}

View file

@ -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