Auto merge of #11659 - aDotInTheVoid:hexdigit, r=Jarcho

[`manual_is_ascii_check`]: Also check for `is_ascii_hexdigt`

changelog: [`manual_is_ascii_check`]: Also check for `is_ascii_hexdigt`
This commit is contained in:
bors 2023-10-12 19:30:32 +00:00
commit ff00e9c8c0
4 changed files with 46 additions and 8 deletions

View file

@ -15,12 +15,13 @@ use rustc_span::{sym, Span};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Suggests to use dedicated built-in methods, /// Suggests to use dedicated built-in methods,
/// `is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range /// `is_ascii_(lowercase|uppercase|digit|hexdigit)` for checking on corresponding
/// ascii range
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// Using the built-in functions is more readable and makes it /// Using the built-in functions is more readable and makes it
/// clear that it's not a specific subset of characters, but all /// clear that it's not a specific subset of characters, but all
/// ASCII (lowercase|uppercase|digit) characters. /// ASCII (lowercase|uppercase|digit|hexdigit) characters.
/// ### Example /// ### Example
/// ```rust /// ```rust
/// fn main() { /// fn main() {
@ -28,6 +29,7 @@ declare_clippy_lint! {
/// assert!(matches!(b'X', b'A'..=b'Z')); /// assert!(matches!(b'X', b'A'..=b'Z'));
/// assert!(matches!('2', '0'..='9')); /// assert!(matches!('2', '0'..='9'));
/// assert!(matches!('x', 'A'..='Z' | 'a'..='z')); /// assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
/// assert!(matches!('C', '0'..='9' | 'a'..='f' | 'A'..='F'));
/// ///
/// ('0'..='9').contains(&'0'); /// ('0'..='9').contains(&'0');
/// ('a'..='z').contains(&'a'); /// ('a'..='z').contains(&'a');
@ -41,6 +43,7 @@ declare_clippy_lint! {
/// assert!(b'X'.is_ascii_uppercase()); /// assert!(b'X'.is_ascii_uppercase());
/// assert!('2'.is_ascii_digit()); /// assert!('2'.is_ascii_digit());
/// assert!('x'.is_ascii_alphabetic()); /// assert!('x'.is_ascii_alphabetic());
/// assert!('C'.is_ascii_hexdigit());
/// ///
/// '0'.is_ascii_digit(); /// '0'.is_ascii_digit();
/// 'a'.is_ascii_lowercase(); /// 'a'.is_ascii_lowercase();
@ -75,6 +78,12 @@ enum CharRange {
FullChar, FullChar,
/// '0..=9' /// '0..=9'
Digit, Digit,
/// 'a..=f'
LowerHexLetter,
/// 'A..=F'
UpperHexLetter,
/// '0..=9' | 'a..=f' | 'A..=F'
HexDigit,
Otherwise, Otherwise,
} }
@ -116,7 +125,8 @@ fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &Cha
CharRange::LowerChar => Some("is_ascii_lowercase"), CharRange::LowerChar => Some("is_ascii_lowercase"),
CharRange::FullChar => Some("is_ascii_alphabetic"), CharRange::FullChar => Some("is_ascii_alphabetic"),
CharRange::Digit => Some("is_ascii_digit"), CharRange::Digit => Some("is_ascii_digit"),
CharRange::Otherwise => None, CharRange::HexDigit => Some("is_ascii_hexdigit"),
CharRange::Otherwise | CharRange::LowerHexLetter | CharRange::UpperHexLetter => None,
} { } {
let default_snip = ".."; let default_snip = "..";
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
@ -141,6 +151,12 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
if ranges.len() == 2 && ranges.contains(&CharRange::UpperChar) && ranges.contains(&CharRange::LowerChar) { if ranges.len() == 2 && ranges.contains(&CharRange::UpperChar) && ranges.contains(&CharRange::LowerChar) {
CharRange::FullChar CharRange::FullChar
} else if ranges.len() == 3
&& ranges.contains(&CharRange::Digit)
&& ranges.contains(&CharRange::LowerHexLetter)
&& ranges.contains(&CharRange::UpperHexLetter)
{
CharRange::HexDigit
} else { } else {
CharRange::Otherwise CharRange::Otherwise
} }
@ -156,6 +172,8 @@ fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
match (&start_lit.node, &end_lit.node) { match (&start_lit.node, &end_lit.node) {
(Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar, (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
(Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar, (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
(Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
(Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
(Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit, (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
_ => CharRange::Otherwise, _ => CharRange::Otherwise,
} }

View file

@ -33,6 +33,7 @@ fn msrv_1_23() {
assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!(b'1', b'0'..=b'9'));
assert!(matches!('X', 'A'..='Z')); assert!(matches!('X', 'A'..='Z'));
assert!(matches!('x', 'A'..='Z' | 'a'..='z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
} }
#[clippy::msrv = "1.24"] #[clippy::msrv = "1.24"]
@ -40,14 +41,17 @@ fn msrv_1_24() {
assert!(b'1'.is_ascii_digit()); assert!(b'1'.is_ascii_digit());
assert!('X'.is_ascii_uppercase()); assert!('X'.is_ascii_uppercase());
assert!('x'.is_ascii_alphabetic()); assert!('x'.is_ascii_alphabetic());
assert!('x'.is_ascii_hexdigit());
} }
#[clippy::msrv = "1.46"] #[clippy::msrv = "1.46"]
fn msrv_1_46() { fn msrv_1_46() {
const FOO: bool = matches!('x', '0'..='9'); const FOO: bool = matches!('x', '0'..='9');
const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
} }
#[clippy::msrv = "1.47"] #[clippy::msrv = "1.47"]
fn msrv_1_47() { fn msrv_1_47() {
const FOO: bool = 'x'.is_ascii_digit(); const FOO: bool = 'x'.is_ascii_digit();
const BAR: bool = 'x'.is_ascii_hexdigit();
} }

View file

@ -33,6 +33,7 @@ fn msrv_1_23() {
assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!(b'1', b'0'..=b'9'));
assert!(matches!('X', 'A'..='Z')); assert!(matches!('X', 'A'..='Z'));
assert!(matches!('x', 'A'..='Z' | 'a'..='z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
} }
#[clippy::msrv = "1.24"] #[clippy::msrv = "1.24"]
@ -40,14 +41,17 @@ fn msrv_1_24() {
assert!(matches!(b'1', b'0'..=b'9')); assert!(matches!(b'1', b'0'..=b'9'));
assert!(matches!('X', 'A'..='Z')); assert!(matches!('X', 'A'..='Z'));
assert!(matches!('x', 'A'..='Z' | 'a'..='z')); assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
} }
#[clippy::msrv = "1.46"] #[clippy::msrv = "1.46"]
fn msrv_1_46() { fn msrv_1_46() {
const FOO: bool = matches!('x', '0'..='9'); const FOO: bool = matches!('x', '0'..='9');
const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
} }
#[clippy::msrv = "1.47"] #[clippy::msrv = "1.47"]
fn msrv_1_47() { fn msrv_1_47() {
const FOO: bool = matches!('x', '0'..='9'); const FOO: bool = matches!('x', '0'..='9');
const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
} }

View file

@ -98,28 +98,40 @@ LL | ('A'..='Z').contains(cool_letter);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()`
error: manual check for common ascii range error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:40:13 --> $DIR/manual_is_ascii_check.rs:41:13
| |
LL | assert!(matches!(b'1', b'0'..=b'9')); LL | assert!(matches!(b'1', b'0'..=b'9'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
error: manual check for common ascii range error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:41:13 --> $DIR/manual_is_ascii_check.rs:42:13
| |
LL | assert!(matches!('X', 'A'..='Z')); LL | assert!(matches!('X', 'A'..='Z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
error: manual check for common ascii range error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:42:13 --> $DIR/manual_is_ascii_check.rs:43:13
| |
LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
error: manual check for common ascii range error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:52:23 --> $DIR/manual_is_ascii_check.rs:44:13
|
LL | assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()`
error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:55:23
| |
LL | const FOO: bool = matches!('x', '0'..='9'); LL | const FOO: bool = matches!('x', '0'..='9');
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
error: aborting due to 20 previous errors error: manual check for common ascii range
--> $DIR/manual_is_ascii_check.rs:56:23
|
LL | const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()`
error: aborting due to 22 previous errors