Skip to content

Commit

Permalink
Check {print,write}_with_newline for literal newline
Browse files Browse the repository at this point in the history
Both regular strings and raw strings can contain literal newlines. This commit
extends the lint to also warn about terminating strings with these.

Behaviour handling for raw strings is also moved into `check_newlines` by
passing in the `is_raw` boolean from `check_tts` as
[suggested](rust-lang/rust-clippy#3781 (review))
  • Loading branch information
uniphil committed Feb 19, 2019
1 parent 3fa3bd8 commit ef72b2c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 5 deletions.
13 changes: 10 additions & 3 deletions clippy_lints/src/write.rs
Expand Up @@ -201,7 +201,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), _, is_raw) = check_tts(cx, &mac.node.tts, false) {
if !is_raw && check_newlines(&fmtstr) {
if check_newlines(&fmtstr, is_raw) {
span_lint(
cx,
PRINT_WITH_NEWLINE,
Expand All @@ -213,7 +213,7 @@ impl EarlyLintPass for Pass {
}
} else if mac.node.path == "write" {
if let (Some(fmtstr), _, is_raw) = check_tts(cx, &mac.node.tts, true) {
if !is_raw && check_newlines(&fmtstr) {
if check_newlines(&fmtstr, is_raw) {
span_lint(
cx,
WRITE_WITH_NEWLINE,
Expand Down Expand Up @@ -382,7 +382,14 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
}

// Checks if `s` constains a single newline that terminates it
fn check_newlines(s: &str) -> bool {
// Literal and escaped newlines are both checked (only literal for raw strings)
fn check_newlines(s: &str, is_raw: bool) -> bool {
if s.ends_with('\n') {
return true;
} else if is_raw {
return false;
}

if s.len() < 2 {
return false;
}
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/print_with_newline.rs
Expand Up @@ -29,4 +29,14 @@ fn main() {

// Raw strings
print!(r"\n"); // #3778

// Literal newlines should also fail
print!(
"
"
);
print!(
r"
"
);
}
20 changes: 19 additions & 1 deletion tests/ui/print_with_newline.stderr
Expand Up @@ -30,5 +30,23 @@ error: using `print!()` with a format string that ends in a single newline, cons
LL | print!("//n"); // should fail
| ^^^^^^^^^^^^^^

error: aborting due to 5 previous errors
error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead
--> $DIR/print_with_newline.rs:34:5
|
LL | / print!(
LL | | "
LL | | "
LL | | );
| |_____^

error: using `print!()` with a format string that ends in a single newline, consider using `println!()` instead
--> $DIR/print_with_newline.rs:38:5
|
LL | / print!(
LL | | r"
LL | | "
LL | | );
| |_____^

error: aborting due to 7 previous errors

12 changes: 12 additions & 0 deletions tests/ui/write_with_newline.rs
Expand Up @@ -34,4 +34,16 @@ fn main() {

// Raw strings
write!(&mut v, r"\n"); // #3778

// Literal newlines should also fail
write!(
&mut v,
"
"
);
write!(
&mut v,
r"
"
);
}
22 changes: 21 additions & 1 deletion tests/ui/write_with_newline.stderr
Expand Up @@ -30,5 +30,25 @@ error: using `write!()` with a format string that ends in a single newline, cons
LL | write!(&mut v, "//n"); // should fail
| ^^^^^^^^^^^^^^^^^^^^^^

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

error: using `write!()` with a format string that ends in a single newline, consider using `writeln!()` instead
--> $DIR/write_with_newline.rs:44:5
|
LL | / write!(
LL | | &mut v,
LL | | r"
LL | | "
LL | | );
| |_____^

error: aborting due to 7 previous errors

0 comments on commit ef72b2c

Please sign in to comment.