about summary refs log tree commit diff
path: root/clippy_lints
diff options
context:
space:
mode:
authorMax Baumann <max@bmn.dev>2022-03-18 23:18:36 +0100
committerMax Baumann <max@bmn.dev>2022-03-18 23:18:36 +0100
commit895de1f13e78de456d5ecbdca3c87526c4dbbef2 (patch)
tree1207ed498325f9aa8a33b3c44c9bb671752e9199 /clippy_lints
parentf00e844a1f3b7e6d8a5d84e90baa37b0cebeac67 (diff)
downloadrust-895de1f13e78de456d5ecbdca3c87526c4dbbef2.tar.gz
rust-895de1f13e78de456d5ecbdca3c87526c4dbbef2.zip
feat: make fixable
Diffstat (limited to 'clippy_lints')
-rw-r--r--clippy_lints/src/methods/or_then_unwrap.rs30
1 files changed, 21 insertions, 9 deletions
diff --git a/clippy_lints/src/methods/or_then_unwrap.rs b/clippy_lints/src/methods/or_then_unwrap.rs
index 578f898da78..4e2dcf67231 100644
--- a/clippy_lints/src/methods/or_then_unwrap.rs
+++ b/clippy_lints/src/methods/or_then_unwrap.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -17,15 +18,20 @@ pub(super) fn check<'tcx>(
 ) {
     let ty = cx.typeck_results().expr_ty(recv); // get type of x (we later check if it's Option or Result)
     let title;
+    let or_arg_content: Span;
 
     if is_type_diagnostic_item(cx, ty, sym::Option) {
         title = ".or(Some(…)).unwrap() found";
-        if !is(or_arg, "Some") {
+        if let Some(content) = get_content_if_is(or_arg, "Some") {
+            or_arg_content = content;
+        } else {
             return;
         }
     } else if is_type_diagnostic_item(cx, ty, sym::Result) {
         title = ".or(Ok(…)).unwrap() found";
-        if !is(or_arg, "Ok") {
+        if let Some(content) = get_content_if_is(or_arg, "Ok") {
+            or_arg_content = content;
+        } else {
             return;
         }
     } else {
@@ -41,30 +47,36 @@ pub(super) fn check<'tcx>(
         unwrap_expr.span
     };
 
+    let mut applicability = Applicability::MachineApplicable;
+    let suggestion = format!(
+        "unwrap_or({})",
+        snippet_with_applicability(cx, or_arg_content, "..", &mut applicability)
+    );
+
     span_lint_and_sugg(
         cx,
         OR_THEN_UNWRAP,
         or_span.to(unwrap_span),
         title,
         "try this",
-        "unwrap_or(...)".into(),
-        Applicability::HasPlaceholders,
+        suggestion,
+        applicability,
     );
 }
 
-/// is expr a Call to name?
+/// is expr a Call to name? if so, return what it's wrapping
 /// name might be "Some", "Ok", "Err", etc.
-fn is<'a>(expr: &Expr<'a>, name: &str) -> bool {
+fn get_content_if_is<'a>(expr: &Expr<'a>, name: &str) -> Option<Span> {
     if_chain! {
-        if let ExprKind::Call(some_expr, _some_args) = expr.kind;
+        if let ExprKind::Call(some_expr, [arg]) = expr.kind;
         if let ExprKind::Path(QPath::Resolved(_, path)) = &some_expr.kind;
         if let Some(path_segment) = path.segments.first();
         if path_segment.ident.name.as_str() == name;
         then {
-            true
+            Some(arg.span)
         }
         else {
-            false
+            None
         }
     }
 }