Skip to content

Commit af8cf94

Browse files
committed
Auto merge of rust-lang#7183 - th1000s:write_nl_hint, r=flip1995
Handle write!(buf, "\n") case better Make `write!(buf, "\n")` suggest `writeln!(buf)` by removing the trailing comma from `writeln!(buf, )`. changelog: [`write_with_newline`] suggestion on only "\n" improved
2 parents 4756667 + 5f3aae6 commit af8cf94

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

clippy_lints/src/write.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,15 @@ impl EarlyLintPass for Write {
279279
span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprintln!`");
280280
self.lint_println_empty_string(cx, mac);
281281
} else if mac.path == sym!(write) {
282-
if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), true) {
282+
if let (Some(fmt_str), dest) = self.check_tts(cx, mac.args.inner_tokens(), true) {
283283
if check_newlines(&fmt_str) {
284+
let (nl_span, only_nl) = newline_span(&fmt_str);
285+
let nl_span = match (dest, only_nl) {
286+
// Special case of `write!(buf, "\n")`: Mark everything from the end of
287+
// `buf` for removal so no trailing comma [`writeln!(buf, )`] remains.
288+
(Some(dest_expr), true) => Span::new(dest_expr.span.hi(), nl_span.hi(), nl_span.ctxt()),
289+
_ => nl_span,
290+
};
284291
span_lint_and_then(
285292
cx,
286293
WRITE_WITH_NEWLINE,
@@ -289,10 +296,7 @@ impl EarlyLintPass for Write {
289296
|err| {
290297
err.multipart_suggestion(
291298
"use `writeln!()` instead",
292-
vec![
293-
(mac.path.span, String::from("writeln")),
294-
(newline_span(&fmt_str), String::new()),
295-
],
299+
vec![(mac.path.span, String::from("writeln")), (nl_span, String::new())],
296300
Applicability::MachineApplicable,
297301
);
298302
},
@@ -329,12 +333,13 @@ impl EarlyLintPass for Write {
329333

330334
/// Given a format string that ends in a newline and its span, calculates the span of the
331335
/// newline, or the format string itself if the format string consists solely of a newline.
332-
fn newline_span(fmtstr: &StrLit) -> Span {
336+
/// Return this and a boolean indicating whether it only consisted of a newline.
337+
fn newline_span(fmtstr: &StrLit) -> (Span, bool) {
333338
let sp = fmtstr.span;
334339
let contents = &fmtstr.symbol.as_str();
335340

336341
if *contents == r"\n" {
337-
return sp;
342+
return (sp, true);
338343
}
339344

340345
let newline_sp_hi = sp.hi()
@@ -351,7 +356,7 @@ fn newline_span(fmtstr: &StrLit) -> Span {
351356
panic!("expected format string to contain a newline");
352357
};
353358

354-
sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
359+
(sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi), false)
355360
}
356361

357362
/// Stores a list of replacement spans for each argument, but only if all the replacements used an
@@ -613,7 +618,7 @@ impl Write {
613618
|err| {
614619
err.multipart_suggestion(
615620
&format!("use `{}!` instead", suggested),
616-
vec![(mac.path.span, suggested), (newline_span(&fmt_str), String::new())],
621+
vec![(mac.path.span, suggested), (newline_span(&fmt_str).0, String::new())],
617622
Applicability::MachineApplicable,
618623
);
619624
},

tests/ui/write_with_newline.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ LL | write!(&mut v, "/n");
5151
|
5252
help: use `writeln!()` instead
5353
|
54-
LL | writeln!(&mut v, );
55-
| ^^^^^^^ --
54+
LL | writeln!(&mut v);
55+
| ^^^^^^^ --
5656

5757
error: using `write!()` with a format string that ends in a single newline
5858
--> $DIR/write_with_newline.rs:36:5

0 commit comments

Comments
 (0)