Skip to content

Commit b8e5e6f

Browse files
committed
Auto merge of #4421 - lzutao:unsep_literal, r=flip1995
Cleaner code for unsep literals Continuing discussion in #4401 (comment) changelog: none r? @flip1995
2 parents 7f15607 + c1a4b26 commit b8e5e6f

5 files changed

+126
-83
lines changed

clippy_lints/src/misc_early.rs

Lines changed: 73 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, Lin
66
use rustc::{declare_lint_pass, declare_tool_lint};
77
use rustc_data_structures::fx::FxHashMap;
88
use rustc_errors::Applicability;
9-
use std::char;
109
use syntax::ast::*;
1110
use syntax::source_map::Span;
1211
use syntax::visit::{walk_expr, FnKind, Visitor};
@@ -391,92 +390,93 @@ impl EarlyLintPass for MiscEarlyLints {
391390

392391
impl MiscEarlyLints {
393392
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
394-
if_chain! {
395-
if let LitKind::Int(value, ..) = lit.node;
396-
if let Some(src) = snippet_opt(cx, lit.span);
397-
if let Some(firstch) = src.chars().next();
398-
if char::to_digit(firstch, 10).is_some();
399-
then {
400-
let mut prev = '\0';
401-
for (idx, ch) in src.chars().enumerate() {
402-
if ch == 'i' || ch == 'u' {
403-
if prev != '_' {
404-
span_lint_and_sugg(
405-
cx,
406-
UNSEPARATED_LITERAL_SUFFIX,
407-
lit.span,
408-
"integer type suffix should be separated by an underscore",
409-
"add an underscore",
410-
format!("{}_{}", &src[0..idx], &src[idx..]),
411-
Applicability::MachineApplicable,
412-
);
413-
}
414-
break;
415-
}
416-
prev = ch;
393+
// The `line!()` macro is compiler built-in and a special case for these lints.
394+
let lit_snip = match snippet_opt(cx, lit.span) {
395+
Some(snip) => {
396+
if snip.contains('!') {
397+
return;
417398
}
418-
if src.starts_with("0x") {
419-
let mut seen = (false, false);
420-
for ch in src.chars() {
421-
match ch {
422-
'a' ..= 'f' => seen.0 = true,
423-
'A' ..= 'F' => seen.1 = true,
424-
'i' | 'u' => break, // start of suffix already
425-
_ => ()
426-
}
399+
snip
400+
},
401+
_ => return,
402+
};
403+
404+
if let LitKind::Int(value, lit_int_type) = lit.node {
405+
let suffix = match lit_int_type {
406+
LitIntType::Signed(ty) => ty.ty_to_string(),
407+
LitIntType::Unsigned(ty) => ty.ty_to_string(),
408+
LitIntType::Unsuffixed => "",
409+
};
410+
411+
let maybe_last_sep_idx = lit_snip.len() - suffix.len() - 1;
412+
// Do not lint when literal is unsuffixed.
413+
if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
414+
span_lint_and_sugg(
415+
cx,
416+
UNSEPARATED_LITERAL_SUFFIX,
417+
lit.span,
418+
"integer type suffix should be separated by an underscore",
419+
"add an underscore",
420+
format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
421+
Applicability::MachineApplicable,
422+
);
423+
}
424+
425+
if lit_snip.starts_with("0x") {
426+
let mut seen = (false, false);
427+
for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() {
428+
match ch {
429+
b'a'..=b'f' => seen.0 = true,
430+
b'A'..=b'F' => seen.1 = true,
431+
_ => {},
427432
}
428433
if seen.0 && seen.1 {
429-
span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span,
430-
"inconsistent casing in hexadecimal literal");
434+
span_lint(
435+
cx,
436+
MIXED_CASE_HEX_LITERALS,
437+
lit.span,
438+
"inconsistent casing in hexadecimal literal",
439+
);
440+
break;
431441
}
432-
} else if src.starts_with("0b") || src.starts_with("0o") {
433-
/* nothing to do */
434-
} else if value != 0 && src.starts_with('0') {
435-
span_lint_and_then(cx,
436-
ZERO_PREFIXED_LITERAL,
437-
lit.span,
438-
"this is a decimal constant",
439-
|db| {
442+
}
443+
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
444+
/* nothing to do */
445+
} else if value != 0 && lit_snip.starts_with('0') {
446+
span_lint_and_then(
447+
cx,
448+
ZERO_PREFIXED_LITERAL,
449+
lit.span,
450+
"this is a decimal constant",
451+
|db| {
440452
db.span_suggestion(
441453
lit.span,
442-
"if you mean to use a decimal constant, remove the `0` to remove confusion",
443-
src.trim_start_matches(|c| c == '_' || c == '0').to_string(),
454+
"if you mean to use a decimal constant, remove the `0` to avoid confusion",
455+
lit_snip.trim_start_matches(|c| c == '_' || c == '0').to_string(),
444456
Applicability::MaybeIncorrect,
445457
);
446458
db.span_suggestion(
447459
lit.span,
448460
"if you mean to use an octal constant, use `0o`",
449-
format!("0o{}", src.trim_start_matches(|c| c == '_' || c == '0')),
461+
format!("0o{}", lit_snip.trim_start_matches(|c| c == '_' || c == '0')),
450462
Applicability::MaybeIncorrect,
451463
);
452-
});
453-
}
464+
},
465+
);
454466
}
455-
}
456-
if_chain! {
457-
if let LitKind::Float(..) = lit.node;
458-
if let Some(src) = snippet_opt(cx, lit.span);
459-
if let Some(firstch) = src.chars().next();
460-
if char::to_digit(firstch, 10).is_some();
461-
then {
462-
let mut prev = '\0';
463-
for (idx, ch) in src.chars().enumerate() {
464-
if ch == 'f' {
465-
if prev != '_' {
466-
span_lint_and_sugg(
467-
cx,
468-
UNSEPARATED_LITERAL_SUFFIX,
469-
lit.span,
470-
"float type suffix should be separated by an underscore",
471-
"add an underscore",
472-
format!("{}_{}", &src[0..idx], &src[idx..]),
473-
Applicability::MachineApplicable,
474-
);
475-
}
476-
break;
477-
}
478-
prev = ch;
479-
}
467+
} else if let LitKind::Float(_, float_ty) = lit.node {
468+
let suffix = float_ty.ty_to_string();
469+
let maybe_last_sep_idx = lit_snip.len() - suffix.len() - 1;
470+
if lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
471+
span_lint_and_sugg(
472+
cx,
473+
UNSEPARATED_LITERAL_SUFFIX,
474+
lit.span,
475+
"float type suffix should be separated by an underscore",
476+
"add an underscore",
477+
format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
478+
Applicability::MachineApplicable,
479+
);
480480
}
481481
}
482482
}

tests/ui/literals.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ LL | let fail_multi_zero = 000_123usize;
2525
| ^^^^^^^^^^^^
2626
|
2727
= note: `-D clippy::zero-prefixed-literal` implied by `-D warnings`
28-
help: if you mean to use a decimal constant, remove the `0` to remove confusion
28+
help: if you mean to use a decimal constant, remove the `0` to avoid confusion
2929
|
3030
LL | let fail_multi_zero = 123usize;
3131
| ^^^^^^^^
@@ -39,7 +39,7 @@ error: this is a decimal constant
3939
|
4040
LL | let fail8 = 0123;
4141
| ^^^^
42-
help: if you mean to use a decimal constant, remove the `0` to remove confusion
42+
help: if you mean to use a decimal constant, remove the `0` to avoid confusion
4343
|
4444
LL | let fail8 = 123;
4545
| ^^^

tests/ui/unseparated_prefix_literals.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#![warn(clippy::unseparated_literal_suffix)]
44
#![allow(dead_code)]
55

6+
macro_rules! lit_from_macro {
7+
() => {
8+
42_usize
9+
};
10+
}
11+
612
fn main() {
713
let _ok1 = 1234_i32;
814
let _ok2 = 1234_isize;
@@ -17,4 +23,12 @@ fn main() {
1723
let _okf2 = 1_f32;
1824
let _failf1 = 1.5_f32;
1925
let _failf2 = 1_f32;
26+
27+
// Test for macro
28+
let _ = lit_from_macro!();
29+
30+
// Counter example
31+
let _ = line!();
32+
// Because `assert!` contains `line!()` macro.
33+
assert_eq!(4897_u32, 32223);
2034
}

tests/ui/unseparated_prefix_literals.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#![warn(clippy::unseparated_literal_suffix)]
44
#![allow(dead_code)]
55

6+
macro_rules! lit_from_macro {
7+
() => {
8+
42usize
9+
};
10+
}
11+
612
fn main() {
713
let _ok1 = 1234_i32;
814
let _ok2 = 1234_isize;
@@ -17,4 +23,12 @@ fn main() {
1723
let _okf2 = 1_f32;
1824
let _failf1 = 1.5f32;
1925
let _failf2 = 1f32;
26+
27+
// Test for macro
28+
let _ = lit_from_macro!();
29+
30+
// Counter example
31+
let _ = line!();
32+
// Because `assert!` contains `line!()` macro.
33+
assert_eq!(4897u32, 32223);
2034
}
Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,61 @@
11
error: integer type suffix should be separated by an underscore
2-
--> $DIR/unseparated_prefix_literals.rs:10:18
2+
--> $DIR/unseparated_prefix_literals.rs:16:18
33
|
44
LL | let _fail1 = 1234i32;
55
| ^^^^^^^ help: add an underscore: `1234_i32`
66
|
77
= note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
88

99
error: integer type suffix should be separated by an underscore
10-
--> $DIR/unseparated_prefix_literals.rs:11:18
10+
--> $DIR/unseparated_prefix_literals.rs:17:18
1111
|
1212
LL | let _fail2 = 1234u32;
1313
| ^^^^^^^ help: add an underscore: `1234_u32`
1414

1515
error: integer type suffix should be separated by an underscore
16-
--> $DIR/unseparated_prefix_literals.rs:12:18
16+
--> $DIR/unseparated_prefix_literals.rs:18:18
1717
|
1818
LL | let _fail3 = 1234isize;
1919
| ^^^^^^^^^ help: add an underscore: `1234_isize`
2020

2121
error: integer type suffix should be separated by an underscore
22-
--> $DIR/unseparated_prefix_literals.rs:13:18
22+
--> $DIR/unseparated_prefix_literals.rs:19:18
2323
|
2424
LL | let _fail4 = 1234usize;
2525
| ^^^^^^^^^ help: add an underscore: `1234_usize`
2626

2727
error: integer type suffix should be separated by an underscore
28-
--> $DIR/unseparated_prefix_literals.rs:14:18
28+
--> $DIR/unseparated_prefix_literals.rs:20:18
2929
|
3030
LL | let _fail5 = 0x123isize;
3131
| ^^^^^^^^^^ help: add an underscore: `0x123_isize`
3232

3333
error: float type suffix should be separated by an underscore
34-
--> $DIR/unseparated_prefix_literals.rs:18:19
34+
--> $DIR/unseparated_prefix_literals.rs:24:19
3535
|
3636
LL | let _failf1 = 1.5f32;
3737
| ^^^^^^ help: add an underscore: `1.5_f32`
3838

3939
error: float type suffix should be separated by an underscore
40-
--> $DIR/unseparated_prefix_literals.rs:19:19
40+
--> $DIR/unseparated_prefix_literals.rs:25:19
4141
|
4242
LL | let _failf2 = 1f32;
4343
| ^^^^ help: add an underscore: `1_f32`
4444

45-
error: aborting due to 7 previous errors
45+
error: integer type suffix should be separated by an underscore
46+
--> $DIR/unseparated_prefix_literals.rs:8:9
47+
|
48+
LL | 42usize
49+
| ^^^^^^^ help: add an underscore: `42_usize`
50+
...
51+
LL | let _ = lit_from_macro!();
52+
| ----------------- in this macro invocation
53+
54+
error: integer type suffix should be separated by an underscore
55+
--> $DIR/unseparated_prefix_literals.rs:33:16
56+
|
57+
LL | assert_eq!(4897u32, 32223);
58+
| ^^^^^^^ help: add an underscore: `4897_u32`
59+
60+
error: aborting due to 9 previous errors
4661

0 commit comments

Comments
 (0)