From bd83650e91a751ad352444b458f9f50549fac208 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Wed, 21 Dec 2022 12:47:39 -0700 Subject: [PATCH 1/4] Suggest using Path for comparing extensions Signed-off-by: Tyler Weaver --- ...se_sensitive_file_extension_comparisons.rs | 38 +++++++-- ...sensitive_file_extension_comparisons.fixed | 64 +++++++++++++++ ...se_sensitive_file_extension_comparisons.rs | 8 +- ...ensitive_file_extension_comparisons.stderr | 82 ++++++++++++++++--- 4 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 tests/ui/case_sensitive_file_extension_comparisons.fixed diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index d226c0bba659..bc9b7a73b5b1 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,7 +1,9 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; 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}; @@ -28,13 +30,39 @@ 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"); + let mut recv_str = Sugg::hir(cx, recv, "").to_string(); + + if is_type_lang_item(cx, recv_ty, LangItem::String) { + recv_str = format!("&{recv_str}"); + } + + if recv_str.contains(".to_lowercase()") { + diag.note("to_lowercase allocates memory, this can be avoided by using Path"); + recv_str = recv_str.replace(".to_lowercase()", ""); + } + + if recv_str.contains(".to_uppercase()") { + diag.note("to_uppercase allocates memory, this can be avoided by using Path"); + recv_str = recv_str.replace(".to_uppercase()", ""); + } + + diag.span_suggestion( + recv.span.to(call_span), + "use std::path::Path", + format!("std::path::Path::new({}) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", + recv_str, ext_str.strip_prefix('.').unwrap()), + Applicability::MaybeIncorrect, + ); + } ); } } diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed new file mode 100644 index 000000000000..a8b5950f2087 --- /dev/null +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -0,0 +1,64 @@ +// run-rustfix +#![warn(clippy::case_sensitive_file_extension_comparisons)] + +use std::string::String; + +struct TestStruct; + +impl TestStruct { + fn ends_with(self, _arg: &str) {} +} + +#[allow(dead_code)] +fn is_rust_file(filename: &str) -> bool { + std::path::Path::new(filename) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) +} + +fn main() { + // std::string::String and &str should trigger the lint failure with .ext12 + let _ = std::path::Path::new(&String::new()) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + let _ = std::path::Path::new("str") + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + + // The test struct should not trigger the lint failure with .ext12 + TestStruct {}.ends_with(".ext12"); + + // std::string::String and &str should trigger the lint failure with .EXT12 + let _ = std::path::Path::new(&String::new()) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + let _ = std::path::Path::new("str") + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + + // This should print a note about how to_lowercase and to_uppercase allocates + let _ = std::path::Path::new(&String::new()) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + let _ = std::path::Path::new(&String::new()) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + + // The test struct should not trigger the lint failure with .EXT12 + TestStruct {}.ends_with(".EXT12"); + + // Should not trigger the lint failure with .eXT12 + let _ = String::new().ends_with(".eXT12"); + let _ = "str".ends_with(".eXT12"); + TestStruct {}.ends_with(".eXT12"); + + // Should not trigger the lint failure with .EXT123 (too long) + let _ = String::new().ends_with(".EXT123"); + let _ = "str".ends_with(".EXT123"); + TestStruct {}.ends_with(".EXT123"); + + // Shouldn't fail if it doesn't start with a dot + let _ = String::new().ends_with("a.ext"); + let _ = "str".ends_with("a.extA"); + TestStruct {}.ends_with("a.ext"); +} diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index 6f0485b5279b..ee9bcd73d52e 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::case_sensitive_file_extension_comparisons)] use std::string::String; @@ -5,9 +6,10 @@ use std::string::String; struct TestStruct; impl TestStruct { - fn ends_with(self, arg: &str) {} + fn ends_with(self, _arg: &str) {} } +#[allow(dead_code)] fn is_rust_file(filename: &str) -> bool { filename.ends_with(".rs") } @@ -24,6 +26,10 @@ fn main() { let _ = String::new().ends_with(".EXT12"); let _ = "str".ends_with(".EXT12"); + // This should print a note about how to_lowercase and to_uppercase allocates + let _ = String::new().to_lowercase().ends_with(".EXT12"); + let _ = String::new().to_uppercase().ends_with(".EXT12"); + // The test struct should not trigger the lint failure with .EXT12 TestStruct {}.ends_with(".EXT12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index a28dd8bd5ad3..33435f086d43 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -1,43 +1,103 @@ error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:12:14 + --> $DIR/case_sensitive_file_extension_comparisons.rs:14:5 | LL | filename.ends_with(".rs") - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead = note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings` +help: use std::path::Path + | +LL ~ std::path::Path::new(filename) +LL + .extension() +LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) + | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:17:27 + --> $DIR/case_sensitive_file_extension_comparisons.rs:19:13 | LL | let _ = String::new().ends_with(".ext12"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new(&String::new()) +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:18:19 + --> $DIR/case_sensitive_file_extension_comparisons.rs:20:13 | LL | let _ = "str".ends_with(".ext12"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new("str") +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:24:27 + --> $DIR/case_sensitive_file_extension_comparisons.rs:26:13 | LL | let _ = String::new().ends_with(".EXT12"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new(&String::new()) +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:25:19 + --> $DIR/case_sensitive_file_extension_comparisons.rs:27:13 | LL | let _ = "str".ends_with(".EXT12"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new("str") +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + | -error: aborting due to 5 previous errors +error: case-sensitive file extension comparison + --> $DIR/case_sensitive_file_extension_comparisons.rs:30:13 + | +LL | let _ = String::new().to_lowercase().ends_with(".EXT12"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using a case-insensitive comparison instead + = note: to_lowercase allocates memory, this can be avoided by using Path +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new(&String::new()) +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + | + +error: case-sensitive file extension comparison + --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13 + | +LL | let _ = String::new().to_uppercase().ends_with(".EXT12"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using a case-insensitive comparison instead + = note: to_uppercase allocates memory, this can be avoided by using Path +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new(&String::new()) +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + | + +error: aborting due to 7 previous errors From 0aa7d73df37470b9f868873587faf64c3339f964 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Mon, 2 Jan 2023 07:12:43 -0700 Subject: [PATCH 2/4] Only remove method from end of recv, indent suggestion source Signed-off-by: Tyler Weaver --- ...se_sensitive_file_extension_comparisons.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index bc9b7a73b5b1..e34c377f5fc3 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::{indent_of, reindent_multiline}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_type_lang_item; use if_chain::if_chain; @@ -37,29 +38,36 @@ pub(super) fn check<'tcx>( "case-sensitive file extension comparison", |diag| { diag.help("consider using a case-insensitive comparison instead"); - let mut recv_str = Sugg::hir(cx, recv, "").to_string(); + let mut recv_source = Sugg::hir(cx, recv, "").to_string(); if is_type_lang_item(cx, recv_ty, LangItem::String) { - recv_str = format!("&{recv_str}"); + recv_source = format!("&{recv_source}"); } - if recv_str.contains(".to_lowercase()") { + if recv_source.ends_with(".to_lowercase()") { diag.note("to_lowercase allocates memory, this can be avoided by using Path"); - recv_str = recv_str.replace(".to_lowercase()", ""); + recv_source = recv_source.strip_suffix(".to_lowercase()").unwrap().to_string(); } - if recv_str.contains(".to_uppercase()") { + if recv_source.ends_with(".to_uppercase()") { diag.note("to_uppercase allocates memory, this can be avoided by using Path"); - recv_str = recv_str.replace(".to_uppercase()", ""); + recv_source = recv_source.strip_suffix(".to_uppercase()").unwrap().to_string(); } + 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", - format!("std::path::Path::new({}) - .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", - recv_str, ext_str.strip_prefix('.').unwrap()), + suggestion_source, Applicability::MaybeIncorrect, ); } From 0cee2c50952a11099692652af367b4fea3cb09a6 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Mon, 2 Jan 2023 16:42:56 -0700 Subject: [PATCH 3/4] Don't trigger lint if last method is to_lower/upper --- ...se_sensitive_file_extension_comparisons.rs | 17 ++++------ ...sensitive_file_extension_comparisons.fixed | 10 ++---- ...se_sensitive_file_extension_comparisons.rs | 2 +- ...ensitive_file_extension_comparisons.stderr | 32 +------------------ 4 files changed, 12 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index e34c377f5fc3..b6ec0fba6cfb 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -18,6 +18,13 @@ pub(super) fn check<'tcx>( recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, ) { + if let ExprKind::MethodCall(path_segment, ..) = recv.kind { + let method_name = path_segment.ident.name.as_str(); + if method_name == "to_lowercase" || method_name == "to_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); @@ -44,16 +51,6 @@ pub(super) fn check<'tcx>( recv_source = format!("&{recv_source}"); } - if recv_source.ends_with(".to_lowercase()") { - diag.note("to_lowercase allocates memory, this can be avoided by using Path"); - recv_source = recv_source.strip_suffix(".to_lowercase()").unwrap().to_string(); - } - - if recv_source.ends_with(".to_uppercase()") { - diag.note("to_uppercase allocates memory, this can be avoided by using Path"); - recv_source = recv_source.strip_suffix(".to_uppercase()").unwrap().to_string(); - } - let suggestion_source = reindent_multiline( format!( "std::path::Path::new({}) diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index a8b5950f2087..a19ed1ddcd54 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -36,13 +36,9 @@ fn main() { .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); - // This should print a note about how to_lowercase and to_uppercase allocates - let _ = std::path::Path::new(&String::new()) - .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); - let _ = std::path::Path::new(&String::new()) - .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase + let _ = String::new().to_lowercase().ends_with(".EXT12"); + let _ = String::new().to_uppercase().ends_with(".EXT12"); // The test struct should not trigger the lint failure with .EXT12 TestStruct {}.ends_with(".EXT12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index ee9bcd73d52e..ad56b7296f75 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -26,7 +26,7 @@ fn main() { let _ = String::new().ends_with(".EXT12"); let _ = "str".ends_with(".EXT12"); - // This should print a note about how to_lowercase and to_uppercase allocates + // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase let _ = String::new().to_lowercase().ends_with(".EXT12"); let _ = String::new().to_uppercase().ends_with(".EXT12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index 33435f086d43..b5c8e4b4fe68 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -69,35 +69,5 @@ LL + .extension() LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); | -error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:30:13 - | -LL | let _ = String::new().to_lowercase().ends_with(".EXT12"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using a case-insensitive comparison instead - = note: to_lowercase allocates memory, this can be avoided by using Path -help: use std::path::Path - | -LL ~ let _ = std::path::Path::new(&String::new()) -LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); - | - -error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13 - | -LL | let _ = String::new().to_uppercase().ends_with(".EXT12"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using a case-insensitive comparison instead - = note: to_uppercase allocates memory, this can be avoided by using Path -help: use std::path::Path - | -LL ~ let _ = std::path::Path::new(&String::new()) -LL + .extension() -LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); - | - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors From ea6ff7ed04b5785d20af03b1e4ac73b4960fa5d5 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Wed, 4 Jan 2023 07:06:07 -0700 Subject: [PATCH 4/4] Apply changes suggested in review --- ...se_sensitive_file_extension_comparisons.rs | 49 ++++++++++--------- ...sensitive_file_extension_comparisons.fixed | 7 +++ ...se_sensitive_file_extension_comparisons.rs | 5 ++ ...ensitive_file_extension_comparisons.stderr | 20 ++++++-- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index b6ec0fba6cfb..0b3bf22743fa 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,6 +1,6 @@ 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::sugg::Sugg; use clippy_utils::ty::is_type_lang_item; use if_chain::if_chain; use rustc_ast::ast::LitKind; @@ -19,8 +19,10 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) { if let ExprKind::MethodCall(path_segment, ..) = recv.kind { - let method_name = path_segment.ident.name.as_str(); - if method_name == "to_lowercase" || method_name == "to_uppercase" { + if matches!( + path_segment.ident.name.as_str(), + "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase" + ) { return; } } @@ -45,28 +47,29 @@ pub(super) fn check<'tcx>( "case-sensitive file extension comparison", |diag| { diag.help("consider using a case-insensitive comparison instead"); - let mut recv_source = Sugg::hir(cx, recv, "").to_string(); + if let Some(mut recv_source) = snippet_opt(cx, recv.span) { - if is_type_lang_item(cx, recv_ty, LangItem::String) { - recv_source = format!("&{recv_source}"); + 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, + ); } - - 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, - ); } ); } diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index a19ed1ddcd54..5fbaa64db39e 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -25,6 +25,13 @@ fn main() { .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + // The fixup should preserve the indentation level + { + let _ = std::path::Path::new("str") + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + } + // The test struct should not trigger the lint failure with .ext12 TestStruct {}.ends_with(".ext12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index ad56b7296f75..3c0d4821f9f3 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -19,6 +19,11 @@ fn main() { let _ = String::new().ends_with(".ext12"); let _ = "str".ends_with(".ext12"); + // The fixup should preserve the indentation level + { + let _ = "str".ends_with(".ext12"); + } + // The test struct should not trigger the lint failure with .ext12 TestStruct {}.ends_with(".ext12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index b5c8e4b4fe68..44c8e3fdf740 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -42,7 +42,21 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:26:13 + --> $DIR/case_sensitive_file_extension_comparisons.rs:24:17 + | +LL | let _ = "str".ends_with(".ext12"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using a case-insensitive comparison instead +help: use std::path::Path + | +LL ~ let _ = std::path::Path::new("str") +LL + .extension() +LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + | + +error: case-sensitive file extension comparison + --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13 | LL | let _ = String::new().ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +70,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); | error: case-sensitive file extension comparison - --> $DIR/case_sensitive_file_extension_comparisons.rs:27:13 + --> $DIR/case_sensitive_file_extension_comparisons.rs:32:13 | LL | let _ = "str".ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,5 +83,5 @@ LL + .extension() LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); | -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors