Skip to content

Commit 0c99de0

Browse files
committed
Add a suggestion
1 parent 99bfee7 commit 0c99de0

File tree

2 files changed

+45
-57
lines changed

2 files changed

+45
-57
lines changed

clippy_lints/src/match_str_case_mismatch.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
use clippy_utils::diagnostics::span_lint_and_help;
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::ty::is_type_diagnostic_item;
33
use rustc_ast::ast::LitKind;
4+
use rustc_errors::Applicability;
45
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
56
use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind};
67
use rustc_lint::{LateContext, LateLintPass};
78
use rustc_middle::hir::map::Map;
89
use rustc_middle::lint::in_external_macro;
910
use rustc_middle::ty;
1011
use rustc_session::{declare_lint_pass, declare_tool_lint};
12+
use rustc_span::symbol::SymbolStr;
1113
use rustc_span::{sym, Span};
1214

1315
declare_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
}
Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,36 @@
1-
error: this `match` expression alters case, but has non-compliant arms
2-
--> $DIR/match_str_case_mismatch.rs:66:5
3-
|
4-
LL | / match var.to_ascii_lowercase().as_str() {
5-
LL | | "foo" => {},
6-
LL | | "Bar" => {},
7-
LL | | _ => {},
8-
LL | | }
9-
| |_____^
10-
|
11-
= note: `-D clippy::match-str-case-mismatch` implied by `-D warnings`
12-
help: consider changing the case of this arm to respect `to_ascii_lowercase`
1+
error: this `match` arm has a differing case than its expression
132
--> $DIR/match_str_case_mismatch.rs:68:9
143
|
154
LL | "Bar" => {},
165
| ^^^^^
17-
18-
error: this `match` expression alters case, but has non-compliant arms
19-
--> $DIR/match_str_case_mismatch.rs:76:5
20-
|
21-
LL | / match &*var.to_ascii_lowercase() {
22-
LL | | "foo" => {},
23-
LL | | "Bar" => {},
24-
LL | | _ => {},
25-
LL | | }
26-
| |_____^
276
|
7+
= note: `-D clippy::match-str-case-mismatch` implied by `-D warnings`
288
help: consider changing the case of this arm to respect `to_ascii_lowercase`
9+
|
10+
LL | "bar" => {},
11+
| ~~~~~
12+
13+
error: this `match` arm has a differing case than its expression
2914
--> $DIR/match_str_case_mismatch.rs:78:9
3015
|
3116
LL | "Bar" => {},
3217
| ^^^^^
33-
34-
error: this `match` expression alters case, but has non-compliant arms
35-
--> $DIR/match_str_case_mismatch.rs:86:5
36-
|
37-
LL | / match &*var
38-
LL | | .to_ascii_lowercase()
39-
LL | | .to_uppercase()
40-
LL | | .to_lowercase()
41-
... |
42-
LL | | _ => {},
43-
LL | | }
44-
| |_____^
4518
|
46-
help: consider changing the case of this arm to respect `to_ascii_uppercase`
19+
help: consider changing the case of this arm to respect `to_ascii_lowercase`
20+
|
21+
LL | "bar" => {},
22+
| ~~~~~
23+
24+
error: this `match` arm has a differing case than its expression
4725
--> $DIR/match_str_case_mismatch.rs:93:9
4826
|
4927
LL | "bAR" => {},
5028
| ^^^^^
29+
|
30+
help: consider changing the case of this arm to respect `to_ascii_uppercase`
31+
|
32+
LL | "BAR" => {},
33+
| ~~~~~
5134

5235
error: aborting due to 3 previous errors
5336

0 commit comments

Comments
 (0)