summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/format.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/format.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs91
1 files changed, 44 insertions, 47 deletions
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index d0fab6949..d34d6e927 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -1,14 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node};
+use clippy_utils::source::{snippet_opt, snippet_with_context};
use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
+use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
declare_clippy_lint! {
@@ -44,55 +43,53 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
impl<'tcx> LateLintPass<'tcx> for UselessFormat {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- let (format_args, call_site) = if_chain! {
- if let Some(macro_call) = root_macro_call_first_node(cx, expr);
- if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id);
- if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn);
- then {
- (format_args, macro_call.span)
- } else {
- return
- }
- };
+ let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
+ if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) {
+ return;
+ }
+
+ find_format_args(cx, expr, macro_call.expn, |format_args| {
+ let mut applicability = Applicability::MachineApplicable;
+ let call_site = macro_call.span;
- let mut applicability = Applicability::MachineApplicable;
- if format_args.args.is_empty() {
- match *format_args.format_string.parts {
- [] => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
- [_] => {
+ match (format_args.arguments.all_args(), &format_args.template[..]) {
+ ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
+ ([], [_]) => {
// Simulate macro expansion, converting {{ and }} to { and }.
- let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}");
+ let Some(snippet) = snippet_opt(cx, format_args.span) else { return };
+ let s_expand = snippet.replace("{{", "{").replace("}}", "}");
let sugg = format!("{s_expand}.to_string()");
span_useless_format(cx, call_site, sugg, applicability);
},
- [..] => {},
- }
- } else if let [arg] = &*format_args.args {
- let value = arg.param.value;
- if_chain! {
- if format_args.format_string.parts == [kw::Empty];
- if arg.format.is_default();
- if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
- ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
- ty::Str => true,
- _ => false,
- };
- then {
- let is_new_string = match value.kind {
- ExprKind::Binary(..) => true,
- ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
- _ => false,
- };
- let sugg = if is_new_string {
- snippet_with_applicability(cx, value.span, "..", &mut applicability).into_owned()
- } else {
- let sugg = Sugg::hir_with_applicability(cx, value, "<arg>", &mut applicability);
- format!("{}.to_string()", sugg.maybe_par())
- };
- span_useless_format(cx, call_site, sugg, applicability);
- }
+ ([arg], [piece]) => {
+ if let Ok(value) = find_format_arg_expr(expr, arg)
+ && let FormatArgsPiece::Placeholder(placeholder) = piece
+ && placeholder.format_trait == FormatTrait::Display
+ && placeholder.format_options == FormatOptions::default()
+ && match cx.typeck_results().expr_ty(value).peel_refs().kind() {
+ ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
+ ty::Str => true,
+ _ => false,
+ }
+ {
+ let is_new_string = match value.kind {
+ ExprKind::Binary(..) => true,
+ ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
+ _ => false,
+ };
+ let sugg = if is_new_string {
+ snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
+ } else {
+ let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
+ format!("{}.to_string()", sugg.maybe_par())
+ };
+ span_useless_format(cx, call_site, sugg, applicability);
+
+ }
+ },
+ _ => {},
}
- };
+ });
}
}