- if mac.path == sym!(print) {
- if !is_build_script(cx) {
- span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`");
- }
- self.lint_print_with_newline(cx, mac);
- } else if mac.path == sym!(println) {
- if !is_build_script(cx) {
- span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`");
- }
- self.lint_println_empty_string(cx, mac);
- } else if mac.path == sym!(eprint) {
- span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprint!`");
- self.lint_print_with_newline(cx, mac);
- } else if mac.path == sym!(eprintln) {
- span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprintln!`");
- self.lint_println_empty_string(cx, mac);
- } else if mac.path == sym!(write) {
- if let (Some(fmt_str), dest) = self.check_tts(cx, mac.args.inner_tokens(), true) {
- if check_newlines(&fmt_str) {
- let (nl_span, only_nl) = newline_span(&fmt_str);
- let nl_span = match (dest, only_nl) {
- // Special case of `write!(buf, "\n")`: Mark everything from the end of
- // `buf` for removal so no trailing comma [`writeln!(buf, )`] remains.
- (Some(dest_expr), true) => nl_span.with_lo(dest_expr.span.hi()),
- _ => nl_span,
- };
- span_lint_and_then(
- cx,
- WRITE_WITH_NEWLINE,
- mac.span(),
- "using `write!()` with a format string that ends in a single newline",
- |err| {
- err.multipart_suggestion(
- "use `writeln!()` instead",
- vec![(mac.path.span, String::from("writeln")), (nl_span, String::new())],
- Applicability::MachineApplicable,
- );
- },
- );
- }
- }
- } else if mac.path == sym!(writeln) {
- if let (Some(fmt_str), expr) = self.check_tts(cx, mac.args.inner_tokens(), true) {
- if fmt_str.symbol == kw::Empty {
- let mut applicability = Applicability::MachineApplicable;
- let suggestion = if let Some(e) = expr {
- snippet_with_applicability(cx, e.span, "v", &mut applicability)
- } else {
- applicability = Applicability::HasPlaceholders;
- Cow::Borrowed("v")
- };
-
- span_lint_and_sugg(
- cx,
- WRITELN_EMPTY_STRING,
- mac.span(),
- format!("using `writeln!({}, \"\")`", suggestion).as_str(),
- "replace it with",
- format!("writeln!({})", suggestion),
- applicability,
- );
+ let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn) else { return };
+
+ // ignore `writeln!(w)` and `write!(v, some_macro!())`
+ if format_args.format_string.span.from_expansion() {
+ return;
+ }
+
+ match diag_name {
+ sym::print_macro | sym::eprint_macro | sym::write_macro => {
+ check_newline(cx, &format_args, ¯o_call, name);
+ },
+ sym::println_macro | sym::eprintln_macro | sym::writeln_macro => {
+ check_empty_string(cx, &format_args, ¯o_call, name);
+ },
+ _ => {},
+ }
+
+ check_literal(cx, &format_args, name);
+
+ if !self.in_debug_impl {
+ for arg in &format_args.args {
+ if arg.format.r#trait == sym::Debug {
+ span_lint(cx, USE_DEBUG, arg.span, "use of `Debug`-based formatting");