]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
Merge commit '7f27e2e74ef957baa382dc05cf08df6368165c74' into clippyup
[rust.git] / src / tools / clippy / clippy_lints / src / methods / case_sensitive_file_extension_comparisons.rs
index d226c0bba6593f4fccfc89237d866d8d8d1784e2..0b3bf22743fae1b0c446c72112b6be8536a1ef4c 100644 (file)
@@ -1,7 +1,10 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_lang_item;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
+use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
 use rustc_span::{source_map::Spanned, Span};
@@ -15,6 +18,15 @@ pub(super) fn check<'tcx>(
     recv: &'tcx Expr<'_>,
     arg: &'tcx Expr<'_>,
 ) {
+    if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
+        if matches!(
+            path_segment.ident.name.as_str(),
+            "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
+        ) {
+            return;
+        }
+    }
+
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
@@ -28,13 +40,37 @@ pub(super) fn check<'tcx>(
         let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
         if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
         then {
-            span_lint_and_help(
+            span_lint_and_then(
                 cx,
                 CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-                call_span,
+                recv.span.to(call_span),
                 "case-sensitive file extension comparison",
-                None,
-                "consider using a case-insensitive comparison instead",
+                |diag| {
+                    diag.help("consider using a case-insensitive comparison instead");
+                    if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
+
+                        if !cx.typeck_results().expr_ty(recv).is_ref() {
+                            recv_source = format!("&{recv_source}");
+                        }
+
+                        let suggestion_source = reindent_multiline(
+                            format!(
+                                "std::path::Path::new({})
+                                    .extension()
+                                    .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
+                                recv_source, ext_str.strip_prefix('.').unwrap()).into(),
+                            true,
+                            Some(indent_of(cx, call_span).unwrap_or(0) + 4)
+                        );
+
+                        diag.span_suggestion(
+                            recv.span.to(call_span),
+                            "use std::path::Path",
+                            suggestion_source,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
             );
         }
     }