better help for mixed_case_hex_literals (#14235)
It can be error-prone for developers to manually change literals with mixed uppercase and lowercase letters into consistently all-lowercase or all-uppercase literals. Therefore, this lint rule should suggest alternative literals. changelog: [`mixed_case_hex_literals`]: add alternative suggestions
This commit is contained in:
commit
dd8cf052c2
3 changed files with 62 additions and 20 deletions
|
|
@ -1,32 +1,51 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::MIXED_CASE_HEX_LITERALS;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_snip: &str) {
|
||||
let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
|
||||
return; // It's useless so shouldn't lint.
|
||||
let num_end_idx = match lit_snip.strip_suffix(suffix) {
|
||||
Some(p) if p.ends_with('_') => lit_snip.len() - (suffix.len() + 1),
|
||||
Some(_) => lit_snip.len() - suffix.len(),
|
||||
None => lit_snip.len(),
|
||||
};
|
||||
if maybe_last_sep_idx <= 2 {
|
||||
|
||||
if num_end_idx <= 2 {
|
||||
// It's meaningless or causes range error.
|
||||
return;
|
||||
}
|
||||
|
||||
let mut seen = (false, false);
|
||||
for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] {
|
||||
for ch in &lit_snip.as_bytes()[2..num_end_idx] {
|
||||
match ch {
|
||||
b'a'..=b'f' => seen.0 = true,
|
||||
b'A'..=b'F' => seen.1 = true,
|
||||
_ => {},
|
||||
}
|
||||
if seen.0 && seen.1 {
|
||||
span_lint(
|
||||
let raw_digits = &lit_snip[2..num_end_idx];
|
||||
let (sugg_lower, sugg_upper) = if suffix.is_empty() {
|
||||
(
|
||||
format!("0x{}", raw_digits.to_lowercase()),
|
||||
format!("0x{}", raw_digits.to_uppercase()),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
format!("0x{}_{}", raw_digits.to_lowercase(), suffix),
|
||||
format!("0x{}_{}", raw_digits.to_uppercase(), suffix),
|
||||
)
|
||||
};
|
||||
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
MIXED_CASE_HEX_LITERALS,
|
||||
lit_span,
|
||||
"inconsistent casing in hexadecimal literal",
|
||||
None,
|
||||
format!("consider using `{sugg_lower}` or `{sugg_upper}`"),
|
||||
);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ fn main() {
|
|||
//~^ separated_literal_suffix
|
||||
//~| mixed_case_hex_literals
|
||||
|
||||
let fail2 = 0xab_CD_isize;
|
||||
//~^ separated_literal_suffix
|
||||
//~| mixed_case_hex_literals
|
||||
|
||||
let fail_multi_zero = 000_123usize;
|
||||
//~^ unseparated_literal_suffix
|
||||
//~| zero_prefixed_literal
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ error: inconsistent casing in hexadecimal literal
|
|||
LL | let fail1 = 0xabCD;
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider using `0xabcd` or `0xABCD`
|
||||
= note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::mixed_case_hex_literals)]`
|
||||
|
||||
|
|
@ -39,6 +40,8 @@ error: inconsistent casing in hexadecimal literal
|
|||
|
|
||||
LL | let fail2 = 0xabCD_u32;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `0xabcd_u32` or `0xABCD_u32`
|
||||
|
||||
error: integer type suffix should not be separated by an underscore
|
||||
--> tests/ui/literals.rs:29:17
|
||||
|
|
@ -51,9 +54,25 @@ error: inconsistent casing in hexadecimal literal
|
|||
|
|
||||
LL | let fail2 = 0xabCD_isize;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `0xabcd_isize` or `0xABCD_isize`
|
||||
|
||||
error: integer type suffix should not be separated by an underscore
|
||||
--> tests/ui/literals.rs:33:17
|
||||
|
|
||||
LL | let fail2 = 0xab_CD_isize;
|
||||
| ^^^^^^^^^^^^^ help: remove the underscore: `0xab_CDisize`
|
||||
|
||||
error: inconsistent casing in hexadecimal literal
|
||||
--> tests/ui/literals.rs:33:17
|
||||
|
|
||||
LL | let fail2 = 0xab_CD_isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `0xab_cd_isize` or `0xAB_CD_isize`
|
||||
|
||||
error: integer type suffix should be separated by an underscore
|
||||
--> tests/ui/literals.rs:33:27
|
||||
--> tests/ui/literals.rs:37:27
|
||||
|
|
||||
LL | let fail_multi_zero = 000_123usize;
|
||||
| ^^^^^^^^^^^^ help: add an underscore: `000_123_usize`
|
||||
|
|
@ -62,7 +81,7 @@ LL | let fail_multi_zero = 000_123usize;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::unseparated_literal_suffix)]`
|
||||
|
||||
error: this is a decimal constant
|
||||
--> tests/ui/literals.rs:33:27
|
||||
--> tests/ui/literals.rs:37:27
|
||||
|
|
||||
LL | let fail_multi_zero = 000_123usize;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
@ -81,13 +100,13 @@ LL + let fail_multi_zero = 0o123usize;
|
|||
|
|
||||
|
||||
error: integer type suffix should not be separated by an underscore
|
||||
--> tests/ui/literals.rs:38:16
|
||||
--> tests/ui/literals.rs:42:16
|
||||
|
|
||||
LL | let ok10 = 0_i64;
|
||||
| ^^^^^ help: remove the underscore: `0i64`
|
||||
|
||||
error: this is a decimal constant
|
||||
--> tests/ui/literals.rs:41:17
|
||||
--> tests/ui/literals.rs:45:17
|
||||
|
|
||||
LL | let fail8 = 0123;
|
||||
| ^^^^
|
||||
|
|
@ -103,13 +122,13 @@ LL | let fail8 = 0o123;
|
|||
| +
|
||||
|
||||
error: integer type suffix should not be separated by an underscore
|
||||
--> tests/ui/literals.rs:51:16
|
||||
--> tests/ui/literals.rs:55:16
|
||||
|
|
||||
LL | let ok17 = 0x123_4567_8901_usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> tests/ui/literals.rs:56:18
|
||||
--> tests/ui/literals.rs:60:18
|
||||
|
|
||||
LL | let fail19 = 12_3456_21;
|
||||
| ^^^^^^^^^^ help: consider: `12_345_621`
|
||||
|
|
@ -118,19 +137,19 @@ LL | let fail19 = 12_3456_21;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> tests/ui/literals.rs:59:18
|
||||
--> tests/ui/literals.rs:63:18
|
||||
|
|
||||
LL | let fail22 = 3__4___23;
|
||||
| ^^^^^^^^^ help: consider: `3_423`
|
||||
|
||||
error: digits grouped inconsistently by underscores
|
||||
--> tests/ui/literals.rs:62:18
|
||||
--> tests/ui/literals.rs:66:18
|
||||
|
|
||||
LL | let fail23 = 3__16___23;
|
||||
| ^^^^^^^^^^ help: consider: `31_623`
|
||||
|
||||
error: digits of hex, binary or octal literal not in groups of equal size
|
||||
--> tests/ui/literals.rs:65:18
|
||||
--> tests/ui/literals.rs:69:18
|
||||
|
|
||||
LL | let fail24 = 0xAB_ABC_AB;
|
||||
| ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB`
|
||||
|
|
@ -139,7 +158,7 @@ LL | let fail24 = 0xAB_ABC_AB;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::unusual_byte_groupings)]`
|
||||
|
||||
error: this is a decimal constant
|
||||
--> tests/ui/literals.rs:75:13
|
||||
--> tests/ui/literals.rs:79:13
|
||||
|
|
||||
LL | let _ = 08;
|
||||
| ^^
|
||||
|
|
@ -151,7 +170,7 @@ LL + let _ = 8;
|
|||
|
|
||||
|
||||
error: this is a decimal constant
|
||||
--> tests/ui/literals.rs:78:13
|
||||
--> tests/ui/literals.rs:82:13
|
||||
|
|
||||
LL | let _ = 09;
|
||||
| ^^
|
||||
|
|
@ -163,7 +182,7 @@ LL + let _ = 9;
|
|||
|
|
||||
|
||||
error: this is a decimal constant
|
||||
--> tests/ui/literals.rs:81:13
|
||||
--> tests/ui/literals.rs:85:13
|
||||
|
|
||||
LL | let _ = 089;
|
||||
| ^^^
|
||||
|
|
@ -174,5 +193,5 @@ LL - let _ = 089;
|
|||
LL + let _ = 89;
|
||||
|
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue