From e587a5d0f08ca138e42bff6f3308bc7950dc6b82 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Mon, 17 Feb 2025 05:36:40 +0900 Subject: [PATCH] better help for `mixed_case_hex_literals` --- .../src/misc_early/mixed_case_hex_literals.rs | 33 +++++++++++--- tests/ui/literals.rs | 4 ++ tests/ui/literals.stderr | 45 +++++++++++++------ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index 9151cc633200..4fbd3c9874db 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -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; } } } diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index d21d49310a07..ba343a8f62f8 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -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 diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index d65cd3c89ebb..6bfeb91625b3 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -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