Add separated_literal_suffix as an alternative for

`unseparated_literal_suffix`

This commit adds a configuration `literal-suffix-style` to enforce a
specific style for unseparated_literal_suffix. The configuration accepts
two values:
- "separated"
    enforce all literals to be written separately (e.g. `123_i32`)
- "unseparated"
    enforce all literals to be written as unseparated (e.g. `123i32`)

Not specifying a value means that there is no preference on style and
any style should not be warned.
This commit is contained in:
Dharma Saputra Wijaya 2021-09-22 22:13:54 +08:00
parent e6e6e7d211
commit 1085df58ac
8 changed files with 149 additions and 58 deletions

View File

@ -323,6 +323,7 @@ store.register_lints(&[
misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
misc_early::MIXED_CASE_HEX_LITERALS,
misc_early::REDUNDANT_PATTERN,
misc_early::SEPARATED_LITERAL_SUFFIX,
misc_early::UNNEEDED_FIELD_PATTERN,
misc_early::UNNEEDED_WILDCARD_PATTERN,
misc_early::UNSEPARATED_LITERAL_SUFFIX,

View File

@ -34,6 +34,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
LintId::of(methods::GET_UNWRAP),
LintId::of(methods::UNWRAP_USED),
LintId::of(misc::FLOAT_CMP_CONST),
LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX),
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),

View File

@ -1,4 +1,3 @@
use super::MiscEarlyLints;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Expr, ExprKind, UnOp};
use rustc_lint::EarlyContext;
@ -6,18 +5,14 @@ use rustc_lint::EarlyContext;
use super::DOUBLE_NEG;
pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) {
match expr.kind {
ExprKind::Unary(UnOp::Neg, ref inner) => {
if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
span_lint(
cx,
DOUBLE_NEG,
expr.span,
"`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
);
}
},
ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit),
_ => (),
if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind {
if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
span_lint(
cx,
DOUBLE_NEG,
expr.span,
"`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
);
}
}
}

View File

@ -0,0 +1,38 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::ast::Lit;
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
val
} else {
return; // It's useless so shouldn't lint.
};
// Do not lint when literal is unsuffixed.
if !suffix.is_empty() {
if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
span_lint_and_sugg(
cx,
SEPARATED_LITERAL_SUFFIX,
lit.span,
&format!("{} type suffix should not be separated by an underscore", sugg_type),
"remove the underscore",
format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
Applicability::MachineApplicable,
);
} else {
span_lint_and_sugg(
cx,
UNSEPARATED_LITERAL_SUFFIX,
lit.span,
&format!("{} type suffix should be separated by an underscore", sugg_type),
"add an underscore",
format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
Applicability::MachineApplicable,
);
}
}
}

View File

@ -1,15 +1,15 @@
mod builtin_type_shadow;
mod double_neg;
mod literal_suffix;
mod mixed_case_hex_literals;
mod redundant_pattern;
mod unneeded_field_pattern;
mod unneeded_wildcard_pattern;
mod unseparated_literal_suffix;
mod zero_prefixed_literal;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
use rustc_ast::visit::FnKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::{EarlyContext, EarlyLintPass};
@ -115,9 +115,11 @@ declare_clippy_lint! {
/// ### What it does
/// Warns if literal suffixes are not separated by an
/// underscore.
/// To enforce unseparated literal suffix style,
/// see the `separated_literal_suffix` lint.
///
/// ### Why is this bad?
/// It is much less readable.
/// Suffix style should be consistent.
///
/// ### Example
/// ```rust
@ -132,6 +134,28 @@ declare_clippy_lint! {
"literals whose suffix is not separated by an underscore"
}
declare_clippy_lint! {
/// ### What it does
/// Warns if literal suffixes are separated by an underscore.
/// To enforce separated literal suffix style,
/// see the `unseparated_literal_suffix` lint.
///
/// ### Why is this bad?
/// Suffix style should be consistent.
///
/// ### Example
/// ```rust
/// // Bad
/// let y = 123832_i32;
///
/// // Good
/// let y = 123832i32;
/// ```
pub SEPARATED_LITERAL_SUFFIX,
restriction,
"literals whose suffix is separated by an underscore"
}
declare_clippy_lint! {
/// ### What it does
/// Warns if an integral constant literal starts with `0`.
@ -260,6 +284,7 @@ declare_lint_pass!(MiscEarlyLints => [
DOUBLE_NEG,
MIXED_CASE_HEX_LITERALS,
UNSEPARATED_LITERAL_SUFFIX,
SEPARATED_LITERAL_SUFFIX,
ZERO_PREFIXED_LITERAL,
BUILTIN_TYPE_SHADOW,
REDUNDANT_PATTERN,
@ -310,6 +335,10 @@ impl EarlyLintPass for MiscEarlyLints {
if in_external_macro(cx.sess, expr.span) {
return;
}
if let ExprKind::Lit(ref lit) = expr.kind {
MiscEarlyLints::check_lit(cx, lit);
}
double_neg::check(cx, expr);
}
}
@ -332,7 +361,7 @@ impl MiscEarlyLints {
LitIntType::Unsigned(ty) => ty.name_str(),
LitIntType::Unsuffixed => "",
};
unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
if lit_snip.starts_with("0x") {
mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
@ -342,7 +371,7 @@ impl MiscEarlyLints {
}
} else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
let suffix = float_ty.name_str();
unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
}
}
}

View File

@ -1,26 +0,0 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::ast::Lit;
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
use super::UNSEPARATED_LITERAL_SUFFIX;
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
val
} else {
return; // It's useless so shouldn't lint.
};
// Do not lint when literal is unsuffixed.
if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
span_lint_and_sugg(
cx,
UNSEPARATED_LITERAL_SUFFIX,
lit.span,
&format!("{} type suffix should be separated by an underscore", sugg_type),
"add an underscore",
format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
Applicability::MachineApplicable,
);
}
}

View File

@ -2,7 +2,8 @@
#![warn(clippy::mixed_case_hex_literals)]
#![warn(clippy::zero_prefixed_literal)]
#![allow(clippy::unseparated_literal_suffix)]
#![warn(clippy::unseparated_literal_suffix)]
#![warn(clippy::separated_literal_suffix)]
#![allow(dead_code)]
fn main() {

View File

@ -1,25 +1,65 @@
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:12:15
|
LL | let ok4 = 0xab_cd_i32;
| ^^^^^^^^^^^ help: remove the underscore: `0xab_cdi32`
|
= note: `-D clippy::separated-literal-suffix` implied by `-D warnings`
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:13:15
|
LL | let ok5 = 0xAB_CD_u32;
| ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32`
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:14:15
|
LL | let ok5 = 0xAB_CD_isize;
| ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize`
error: inconsistent casing in hexadecimal literal
--> $DIR/literals.rs:14:17
--> $DIR/literals.rs:15:17
|
LL | let fail1 = 0xabCD;
| ^^^^^^
|
= note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings`
error: inconsistent casing in hexadecimal literal
--> $DIR/literals.rs:15:17
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:16:17
|
LL | let fail2 = 0xabCD_u32;
| ^^^^^^^^^^
| ^^^^^^^^^^ help: remove the underscore: `0xabCDu32`
error: inconsistent casing in hexadecimal literal
--> $DIR/literals.rs:16:17
|
LL | let fail2 = 0xabCD_u32;
| ^^^^^^^^^^
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:17:17
|
LL | let fail2 = 0xabCD_isize;
| ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize`
error: inconsistent casing in hexadecimal literal
--> $DIR/literals.rs:17:17
|
LL | let fail2 = 0xabCD_isize;
| ^^^^^^^^^^^^
error: integer type suffix should be separated by an underscore
--> $DIR/literals.rs:18:27
|
LL | let fail_multi_zero = 000_123usize;
| ^^^^^^^^^^^^ help: add an underscore: `000_123_usize`
|
= note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
error: this is a decimal constant
--> $DIR/literals.rs:17:27
--> $DIR/literals.rs:18:27
|
LL | let fail_multi_zero = 000_123usize;
| ^^^^^^^^^^^^
@ -34,8 +74,14 @@ help: if you mean to use an octal constant, use `0o`
LL | let fail_multi_zero = 0o123usize;
| ~~~~~~~~~~
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:21:16
|
LL | let ok10 = 0_i64;
| ^^^^^ help: remove the underscore: `0i64`
error: this is a decimal constant
--> $DIR/literals.rs:21:17
--> $DIR/literals.rs:22:17
|
LL | let fail8 = 0123;
| ^^^^
@ -49,8 +95,14 @@ help: if you mean to use an octal constant, use `0o`
LL | let fail8 = 0o123;
| ~~~~~
error: integer type suffix should not be separated by an underscore
--> $DIR/literals.rs:31:16
|
LL | let ok17 = 0x123_4567_8901_usize;
| ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize`
error: digits grouped inconsistently by underscores
--> $DIR/literals.rs:33:18
--> $DIR/literals.rs:34:18
|
LL | let fail19 = 12_3456_21;
| ^^^^^^^^^^ help: consider: `12_345_621`
@ -58,19 +110,19 @@ LL | let fail19 = 12_3456_21;
= note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
error: digits grouped inconsistently by underscores
--> $DIR/literals.rs:34:18
--> $DIR/literals.rs:35:18
|
LL | let fail22 = 3__4___23;
| ^^^^^^^^^ help: consider: `3_423`
error: digits grouped inconsistently by underscores
--> $DIR/literals.rs:35:18
--> $DIR/literals.rs:36:18
|
LL | let fail23 = 3__16___23;
| ^^^^^^^^^^ help: consider: `31_623`
error: digits of hex or binary literal not grouped by four
--> $DIR/literals.rs:37:18
--> $DIR/literals.rs:38:18
|
LL | let fail24 = 0xAB_ABC_AB;
| ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB`
@ -78,10 +130,10 @@ LL | let fail24 = 0xAB_ABC_AB;
= note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
error: digits of hex or binary literal not grouped by four
--> $DIR/literals.rs:38:18
--> $DIR/literals.rs:39:18
|
LL | let fail25 = 0b01_100_101;
| ^^^^^^^^^^^^ help: consider: `0b0110_0101`
error: aborting due to 10 previous errors
error: aborting due to 18 previous errors