|
1 | 1 | use crate::utils::sugg::Sugg;
|
2 |
| -use crate::utils::{match_type, match_qpath, paths, span_lint_and_sugg}; |
| 2 | +use crate::utils::{match_qpath, match_type, paths, span_lint, span_lint_and_sugg}; |
3 | 3 | use if_chain::if_chain;
|
4 | 4 |
|
5 | 5 | use rustc_errors::Applicability;
|
@@ -42,54 +42,61 @@ declare_clippy_lint! {
|
42 | 42 |
|
43 | 43 | declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);
|
44 | 44 |
|
45 |
| -/// If this is the option_if_let_else thing we're detecting, then this |
46 |
| -/// function returns Some(Option<_> compared, value if Option is Some, |
47 |
| -/// value if Option is None). Otherwise, it returns None |
| 45 | +/// If this is the option if let/else thing we're detecting, then this |
| 46 | +/// function returns Some(Option<_> compared, expression if Option is |
| 47 | +/// Some, expression if Option is None). Otherwise, it returns None |
48 | 48 | fn detect_option_if_let_else<'a>(
|
49 | 49 | cx: &LateContext<'_, '_>,
|
50 | 50 | expr: &'a Expr<'_>,
|
51 | 51 | ) -> Option<(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>)> {
|
52 |
| - if_chain! { |
53 |
| - if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar { contains_else_clause: true } ) = &expr.kind; |
54 |
| - if arms.len() == 2; |
55 |
| - if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION); |
56 |
| - if let PatKind::TupleStruct(path, &[inner_pat], _) = &arms[0].pat.kind; |
57 |
| - if let PatKind::Wild | PatKind::Binding(..) = &inner_pat.kind; |
58 |
| - then { |
59 |
| - let (some_body, none_body) = if match_qpath(path, &paths::OPTION_SOME) { |
60 |
| - (arms[0].body, arms[1].body) |
61 |
| - } else { |
62 |
| - (arms[1].body, arms[0].body) |
63 |
| - }; |
64 |
| - Some((let_body, some_body, none_body)) |
65 |
| - } else { |
66 |
| - None |
| 52 | + if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind { |
| 53 | + dbg!("Found if let/else stmt"); |
| 54 | + if arms.len() == 2 { |
| 55 | + dbg!("If let/else statement has two arms"); |
| 56 | + if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION) { |
| 57 | + dbg!("rhs of if let is Option<T>"); |
| 58 | + if let PatKind::TupleStruct(path, &[inner_pat], _) = &arms[0].pat.kind { |
| 59 | + dbg!("arm0 is TupleStruct"); |
| 60 | + if let PatKind::Wild | PatKind::Binding(..) = &inner_pat.kind { |
| 61 | + dbg!("inside of Some(x) matches anything"); |
| 62 | + let (some_body, none_body) = if match_qpath(path, &paths::OPTION_SOME) { |
| 63 | + (arms[0].body, arms[1].body) |
| 64 | + } else { |
| 65 | + (arms[1].body, arms[0].body) |
| 66 | + }; |
| 67 | + return Some((let_body, some_body, none_body)); |
| 68 | + } |
| 69 | + } |
| 70 | + } |
67 | 71 | }
|
68 | 72 | }
|
| 73 | + None |
69 | 74 | }
|
70 | 75 |
|
71 |
| -/// Lint the option_if_let_else thing we're avoiding |
72 |
| -fn check_option_if_let_else(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { |
73 |
| - if let Some((option, map, else_func)) = detect_option_if_let_else(cx, expr) { |
74 |
| - span_lint_and_sugg( |
| 76 | +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse { |
| 77 | + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { |
| 78 | + span_lint( |
75 | 79 | cx,
|
76 | 80 | OPTION_IF_LET_ELSE,
|
77 | 81 | expr.span,
|
78 |
| - "use Option::map_or here", |
79 |
| - "try", |
80 |
| - format!( |
81 |
| - "{}.map_or({}, {})", |
82 |
| - Sugg::hir(cx, option, ".."), |
83 |
| - Sugg::hir(cx, else_func, ".."), |
84 |
| - Sugg::hir(cx, map, "..") |
85 |
| - ), |
86 |
| - Applicability::MachineApplicable, |
| 82 | + "OptionIfLetElse::check_expr was run on this span", |
87 | 83 | );
|
88 |
| - } |
89 |
| -} |
90 |
| - |
91 |
| -impl LateLintPass<'_, '_> for OptionIfLetElse { |
92 |
| - fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { |
93 |
| - check_option_if_let_else(cx, expr); |
| 84 | + return; |
| 85 | + if let Some((option, map, else_func)) = detect_option_if_let_else(cx, expr) { |
| 86 | + span_lint_and_sugg( |
| 87 | + cx, |
| 88 | + OPTION_IF_LET_ELSE, |
| 89 | + expr.span, |
| 90 | + "use Option::map_or_else instead of an if let/else", |
| 91 | + "try", |
| 92 | + format!( |
| 93 | + "{}.map_or_else({}, {})", |
| 94 | + Sugg::hir(cx, option, ".."), |
| 95 | + Sugg::hir(cx, else_func, ".."), |
| 96 | + Sugg::hir(cx, map, "..") |
| 97 | + ), |
| 98 | + Applicability::MachineApplicable, |
| 99 | + ); |
| 100 | + } |
94 | 101 | }
|
95 | 102 | }
|
0 commit comments