Skip to content

Commit e67d2b2

Browse files
author
Donald Robertson
committed
Added check to ensure format macro only being handled, refactored extraction and checks to smaller functions.
1 parent 451fd5f commit e67d2b2

File tree

1 file changed

+48
-36
lines changed

1 file changed

+48
-36
lines changed

clippy_lints/src/methods.rs

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use std::fmt;
77
use std::iter;
88
use syntax::ast;
99
use syntax::codemap::{Span, BytePos};
10-
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_self, is_self_ty,
11-
iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
10+
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
11+
is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
1212
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
1313
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
1414
use crate::utils::paths;
@@ -994,6 +994,34 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
994994

995995
/// Checks for the `EXPECT_FUN_CALL` lint.
996996
fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
997+
fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec<hir::Expr>> {
998+
if let hir::ExprAddrOf(_, ref addr_of) = arg.node {
999+
if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node {
1000+
if let Some(_) = is_expn_of(inner_fun.span, "format") {
1001+
if inner_args.len() == 1 {
1002+
if let hir::ExprCall(_, ref format_args) = inner_args[0].node {
1003+
return Some(format_args);
1004+
}
1005+
}
1006+
}
1007+
}
1008+
}
1009+
1010+
None
1011+
}
1012+
1013+
fn generate_format_arg_snippet(cx: &LateContext, a: &hir::Expr) -> String {
1014+
if let hir::ExprAddrOf(_, ref format_arg) = a.node {
1015+
if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node {
1016+
if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node {
1017+
return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned();
1018+
}
1019+
}
1020+
};
1021+
1022+
snippet(cx, a.span, "..").into_owned()
1023+
}
1024+
9971025
fn check_general_case(
9981026
cx: &LateContext,
9991027
name: &str,
@@ -1024,42 +1052,26 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
10241052
let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" };
10251053
let span_replace_word = method_span.with_hi(span.hi());
10261054

1027-
if let hir::ExprAddrOf(_, ref addr_of) = arg.node {
1028-
if let hir::ExprCall(ref _inner_fun, ref inner_args) = addr_of.node {
1029-
// TODO: check if inner_fun is call to format!
1030-
if inner_args.len() == 1 {
1031-
if let hir::ExprCall(_, ref format_args) = inner_args[0].node {
1032-
let args_len = format_args.len();
1033-
let args: Vec<String> = format_args
1034-
.into_iter()
1035-
.take(args_len - 1)
1036-
.map(|a| {
1037-
if let hir::ExprAddrOf(_, ref format_arg) = a.node {
1038-
if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node {
1039-
if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node {
1040-
return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned();
1041-
}
1042-
}
1043-
};
1044-
snippet(cx, a.span, "..").into_owned()
1045-
})
1046-
.collect();
1047-
1048-
let sugg = args.join(", ");
1055+
if let Some(format_args) = extract_format_args(arg) {
1056+
let args_len = format_args.len();
1057+
let args: Vec<String> = format_args
1058+
.into_iter()
1059+
.take(args_len - 1)
1060+
.map(|a| generate_format_arg_snippet(cx, a))
1061+
.collect();
10491062

1050-
span_lint_and_sugg(
1051-
cx,
1052-
EXPECT_FUN_CALL,
1053-
span_replace_word,
1054-
&format!("use of `{}` followed by a function call", name),
1055-
"try this",
1056-
format!("unwrap_or_else({} panic!({}))", closure, sugg),
1057-
);
1063+
let sugg = args.join(", ");
10581064

1059-
return;
1060-
}
1061-
}
1062-
}
1065+
span_lint_and_sugg(
1066+
cx,
1067+
EXPECT_FUN_CALL,
1068+
span_replace_word,
1069+
&format!("use of `{}` followed by a function call", name),
1070+
"try this",
1071+
format!("unwrap_or_else({} panic!({}))", closure, sugg),
1072+
);
1073+
1074+
return;
10631075
}
10641076

10651077
let sugg: Cow<_> = snippet(cx, arg.span, "..");

0 commit comments

Comments
 (0)