1- use clippy_utils:: diagnostics:: span_lint_and_help ;
1+ use clippy_utils:: diagnostics:: span_lint_and_sugg ;
22use clippy_utils:: ty:: is_type_diagnostic_item;
33use rustc_ast:: ast:: LitKind ;
4+ use rustc_errors:: Applicability ;
45use rustc_hir:: intravisit:: { walk_expr, NestedVisitorMap , Visitor } ;
56use rustc_hir:: { Arm , Expr , ExprKind , MatchSource , PatKind } ;
67use rustc_lint:: { LateContext , LateLintPass } ;
78use rustc_middle:: hir:: map:: Map ;
89use rustc_middle:: lint:: in_external_macro;
910use rustc_middle:: ty;
1011use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
12+ use rustc_span:: symbol:: SymbolStr ;
1113use rustc_span:: { sym, Span } ;
1214
1315declare_clippy_lint ! {
@@ -18,15 +20,19 @@ declare_clippy_lint! {
1820 /// The arm is unreachable, which is likely a mistake
1921 ///
2022 /// ### Example
21- /// ```rust,no_run
23+ /// ```rust
24+ /// # let text = "Foo";
25+ ///
2226 /// match &*text.to_ascii_lowercase() {
2327 /// "foo" => {},
2428 /// "Bar" => {},
2529 /// _ => {},
2630 /// }
2731 /// ```
2832 /// Use instead:
29- /// ```rust,no_run
33+ /// ```rust
34+ /// # let text = "Foo";
35+ ///
3036 /// match &*text.to_ascii_lowercase() {
3137 /// "foo" => {},
3238 /// "bar" => {},
@@ -64,8 +70,8 @@ impl LateLintPass<'_> for MatchStrCaseMismatch {
6470 visitor. visit_expr( match_expr) ;
6571
6672 if let Some ( case_method) = visitor. case_method {
67- if let Some ( bad_case ) = verify_case( & case_method, arms) {
68- lint( cx, expr . span , & case_method, bad_case ) ;
73+ if let Some ( ( bad_case_span , bad_case_str ) ) = verify_case( & case_method, arms) {
74+ lint( cx, & case_method, bad_case_span , & bad_case_str ) ;
6975 }
7076 }
7177 }
@@ -119,9 +125,7 @@ fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> {
119125 }
120126}
121127
122- fn verify_case ( case_method : & CaseMethod , arms : & ' _ [ Arm < ' _ > ] ) -> Option < Span > {
123- let mut bad_case = None ;
124-
128+ fn verify_case < ' a > ( case_method : & ' a CaseMethod , arms : & ' a [ Arm < ' _ > ] ) -> Option < ( Span , SymbolStr ) > {
125129 let case_check = match case_method {
126130 CaseMethod :: LowerCase => |input : & str | -> bool { input. chars ( ) . all ( char:: is_lowercase) } ,
127131 CaseMethod :: AsciiLowerCase => |input : & str | -> bool { input. chars ( ) . all ( |c| matches ! ( c, 'a' ..='z' ) ) } ,
@@ -136,31 +140,32 @@ fn verify_case(case_method: &CaseMethod, arms: &'_ [Arm<'_>]) -> Option<Span> {
136140 ..
137141 } ) = arm. pat. kind;
138142 if let LitKind :: Str ( symbol, _) = lit. node;
139- if !case_check( & symbol. as_str( ) ) ;
143+ let input = symbol. as_str( ) ;
144+ if !case_check( & input) ;
140145 then {
141- bad_case = Some ( lit. span) ;
142- break ;
146+ return Some ( ( lit. span, input) ) ;
143147 }
144148 }
145149 }
146150
147- bad_case
151+ None
148152}
149153
150- fn lint ( cx : & LateContext < ' _ > , expr_span : Span , case_method : & CaseMethod , bad_case_span : Span ) {
151- let method_str = match case_method {
152- CaseMethod :: LowerCase => "to_lower_case" ,
153- CaseMethod :: AsciiLowerCase => "to_ascii_lowercase" ,
154- CaseMethod :: UpperCase => "to_uppercase" ,
155- CaseMethod :: AsciiUppercase => "to_ascii_uppercase" ,
154+ fn lint ( cx : & LateContext < ' _ > , case_method : & CaseMethod , bad_case_span : Span , bad_case_str : & str ) {
155+ let ( method_str, suggestion ) = match case_method {
156+ CaseMethod :: LowerCase => ( "to_lower_case" , bad_case_str . to_lowercase ( ) ) ,
157+ CaseMethod :: AsciiLowerCase => ( "to_ascii_lowercase" , bad_case_str . to_ascii_lowercase ( ) ) ,
158+ CaseMethod :: UpperCase => ( "to_uppercase" , bad_case_str . to_uppercase ( ) ) ,
159+ CaseMethod :: AsciiUppercase => ( "to_ascii_uppercase" , bad_case_str . to_ascii_uppercase ( ) ) ,
156160 } ;
157161
158- span_lint_and_help (
162+ span_lint_and_sugg (
159163 cx,
160164 MATCH_STR_CASE_MISMATCH ,
161- expr_span,
162- "this `match` expression alters case, but has non-compliant arms" ,
163- Some ( bad_case_span) ,
165+ bad_case_span,
166+ "this `match` arm has a differing case than its expression" ,
164167 & * format ! ( "consider changing the case of this arm to respect `{}`" , method_str) ,
168+ format ! ( "\" {}\" " , suggestion) ,
169+ Applicability :: MachineApplicable ,
165170 ) ;
166171}
0 commit comments