1
- // noise reduction, remove before committing!
2
- #![ allow( unused_variables) ]
3
-
4
1
use clippy_utils:: diagnostics:: span_lint_and_sugg;
5
2
use clippy_utils:: source:: snippet_with_applicability;
6
3
use clippy_utils:: { fn_def_id, match_def_path} ;
@@ -22,16 +19,18 @@ declare_clippy_lint! {
22
19
///
23
20
/// ### Example
24
21
/// ```no_run
25
- /// // example code where clippy issues a warning
22
+ /// let x = Some("foo".to_string());
23
+ /// let _y = x.clone().and_then(|v| v.starts_with('f').then_some(v));
26
24
/// ```
27
25
/// Use instead:
28
26
/// ```no_run
29
- /// // example code which does not raise clippy warning
27
+ /// let x = Some("foo".to_string());
28
+ /// let _y = x.clone().filter(|v| v.starts_with('f'));
30
29
/// ```
31
30
#[ clippy:: version = "1.81.0" ]
32
31
pub AND_THEN_THEN_SOME ,
33
32
nursery,
34
- "default lint description "
33
+ "detects usage of and_then and then_some that can be replaced by filter "
35
34
}
36
35
37
36
// note: `Option::filter` is older than `bool::then_some`,
@@ -41,28 +40,16 @@ declare_lint_pass!(AndThenThenSome => [AND_THEN_THEN_SOME]);
41
40
impl < ' tcx > LateLintPass < ' tcx > for AndThenThenSome {
42
41
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
43
42
match expr. kind {
44
- ExprKind :: MethodCall ( method_name, selfarg, [ arg] , _span) => {
45
- //let option_id = cx.tcx.get_diagnostic_item(sym::Option);
46
- // TODO: check if type of reciever is diagnostic item Option.
47
- //let tckr = cx.typeck_results();
48
- //let def_id = tckr.type_dependent_def_id(expr.hir_id).unwrap();
49
- //(method_name, selfarg, arg);
43
+ ExprKind :: MethodCall ( _, selfarg, [ arg] , _) |
44
+ ExprKind :: Call ( _, [ selfarg, arg] )
45
+ => {
46
+ // TODO: check if type of reciever is diagnostic item Option?
50
47
if is_and_then ( cx, expr) {
51
48
if let Some ( ( closure_args, predicate) ) = then_some_closure_arg ( cx, arg) {
52
- //(predicate);
53
49
show_sugg ( cx, expr. span , selfarg, closure_args, predicate) ;
54
50
}
55
51
}
56
52
} ,
57
- ExprKind :: Call ( _func, [ selfarg, arg] ) => {
58
- if is_and_then ( cx, expr) {
59
- if let Some ( ( closure_args, predicate) ) = then_some_closure_arg ( cx, arg) {
60
- //(predicate);
61
- show_sugg ( cx, expr. span , selfarg, closure_args, predicate) ;
62
- }
63
- }
64
- } ,
65
- // TODO: check for call as associated function
66
53
_ => { } ,
67
54
}
68
55
}
@@ -80,7 +67,6 @@ fn then_some_closure_arg<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Opt
80
67
..
81
68
} ) => {
82
69
if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id ) {
83
- //(arg_id);
84
70
( peel_closure_body ( cx, expr, * arg_id) ) . map ( |body| ( cx. tcx . hir ( ) . span ( * arg_id) , body) )
85
71
} else {
86
72
None
@@ -105,16 +91,9 @@ fn peel_closure_body<'tcx>(
105
91
} ,
106
92
_,
107
93
) => peel_closure_body ( cx, wrapped_expr, closure_arg_id) ,
108
- ExprKind :: MethodCall ( _path, selfarg, [ arg] , _span) => {
94
+ ExprKind :: MethodCall ( _, pred, [ arg] , _) |
95
+ ExprKind :: Call ( _, [ pred, arg] ) => {
109
96
if is_then_some ( cx, expr) && is_local_defined_at ( cx, arg, closure_arg_id) {
110
- // the argument to then_some is the same as that given to the closure
111
- Some ( selfarg)
112
- } else {
113
- None
114
- }
115
- } ,
116
- ExprKind :: Call ( func, [ pred, arg] ) => {
117
- if ( is_then_some ( cx, expr) ) && ( is_local_defined_at ( cx, arg, closure_arg_id) ) {
118
97
Some ( pred)
119
98
} else {
120
99
None
0 commit comments