@@ -7,8 +7,8 @@ use std::fmt;
7
7
use std:: iter;
8
8
use syntax:: ast;
9
9
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,
12
12
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
13
13
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth} ;
14
14
use crate :: utils:: paths;
@@ -994,6 +994,34 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
994
994
995
995
/// Checks for the `EXPECT_FUN_CALL` lint.
996
996
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
+
997
1025
fn check_general_case (
998
1026
cx : & LateContext ,
999
1027
name : & str ,
@@ -1024,42 +1052,26 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
1024
1052
let closure = if match_type ( cx, self_type, & paths:: OPTION ) { "||" } else { "|_|" } ;
1025
1053
let span_replace_word = method_span. with_hi ( span. hi ( ) ) ;
1026
1054
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 ( ) ;
1049
1062
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 ( ", " ) ;
1058
1064
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 ;
1063
1075
}
1064
1076
1065
1077
let sugg: Cow < _ > = snippet ( cx, arg. span , ".." ) ;
0 commit comments