mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #8933 - DennisOSRM:needless_braces_range_literal, r=dswij
Add new lint [`needless_parens_on_range_literals`] changelog: Adds a new lint [`needless_parens_on_range_literals`] to warn on needless braces on literals in a range statement For example, the lint would catch ```log error: needless parenthesis on range literals can be removed --> $DIR/needless_parens_on_range_literals.rs:8:13 | LL | let _ = ('a')..=('z'); | ^^^^^ help: try: `'a'` | = note: `-D clippy::needless-parens-on-range-literals` implied by `-D warnings` ```
This commit is contained in:
commit
0f6e50fe1b
@ -3605,6 +3605,7 @@ Released 2018-09-13
|
||||
[`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match
|
||||
[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
|
||||
[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
|
||||
[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
|
||||
[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
|
||||
[`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
|
||||
[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
|
||||
|
@ -242,6 +242,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
||||
LintId::of(needless_bool::NEEDLESS_BOOL),
|
||||
LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
|
||||
LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
|
||||
LintId::of(needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS),
|
||||
LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
|
||||
LintId::of(needless_update::NEEDLESS_UPDATE),
|
||||
LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
|
||||
|
@ -408,6 +408,7 @@ store.register_lints(&[
|
||||
needless_continue::NEEDLESS_CONTINUE,
|
||||
needless_for_each::NEEDLESS_FOR_EACH,
|
||||
needless_late_init::NEEDLESS_LATE_INIT,
|
||||
needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS,
|
||||
needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
|
||||
needless_question_mark::NEEDLESS_QUESTION_MARK,
|
||||
needless_update::NEEDLESS_UPDATE,
|
||||
|
@ -91,6 +91,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
|
||||
LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
|
||||
LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
|
||||
LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
|
||||
LintId::of(needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS),
|
||||
LintId::of(neg_multiply::NEG_MULTIPLY),
|
||||
LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
|
||||
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
|
||||
|
@ -315,6 +315,7 @@ mod needless_borrowed_ref;
|
||||
mod needless_continue;
|
||||
mod needless_for_each;
|
||||
mod needless_late_init;
|
||||
mod needless_parens_on_range_literals;
|
||||
mod needless_pass_by_value;
|
||||
mod needless_question_mark;
|
||||
mod needless_update;
|
||||
@ -746,6 +747,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
|
||||
store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements));
|
||||
store.register_early_pass(|| Box::new(precedence::Precedence));
|
||||
store.register_late_pass(|| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
|
||||
store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue));
|
||||
store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
|
||||
store.register_late_pass(|| Box::new(create_dir::CreateDir));
|
||||
|
87
clippy_lints/src/needless_parens_on_range_literals.rs
Normal file
87
clippy_lints/src/needless_parens_on_range_literals.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_then,
|
||||
higher,
|
||||
source::{snippet, snippet_with_applicability},
|
||||
};
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// The lint checks for parenthesis on literals in range statements that are
|
||||
/// superfluous.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Having superfluous parenthesis makes the code less readable
|
||||
/// overhead when reading.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// for i in (0)..10 {
|
||||
/// println!("{i}");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
///
|
||||
/// ```rust
|
||||
/// for i in 0..10 {
|
||||
/// println!("{i}");
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.63.0"]
|
||||
pub NEEDLESS_PARENS_ON_RANGE_LITERALS,
|
||||
style,
|
||||
"needless parenthesis on range literals can be removed"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NeedlessParensOnRangeLiterals => [NEEDLESS_PARENS_ON_RANGE_LITERALS]);
|
||||
|
||||
fn snippet_enclosed_in_parenthesis(snippet: &str) -> bool {
|
||||
snippet.starts_with('(') && snippet.ends_with(')')
|
||||
}
|
||||
|
||||
fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) {
|
||||
if is_start &&
|
||||
let ExprKind::Lit(ref literal) = e.kind &&
|
||||
let ast::LitKind::Float(_sym, ast::LitFloatType::Unsuffixed) = literal.node
|
||||
{
|
||||
// don't check floating point literals on the start expression of a range
|
||||
return;
|
||||
}
|
||||
if_chain! {
|
||||
if let ExprKind::Lit(ref literal) = e.kind;
|
||||
// the indicator that parenthesis surround the literal is that the span of the expression and the literal differ
|
||||
if (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo);
|
||||
// inspect the source code of the expression for parenthesis
|
||||
if snippet_enclosed_in_parenthesis(&snippet(cx, e.span, ""));
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_then(cx, NEEDLESS_PARENS_ON_RANGE_LITERALS, e.span,
|
||||
"needless parenthesis on range literals can be removed",
|
||||
|diag| {
|
||||
let suggestion = snippet_with_applicability(cx, literal.span, "_", &mut applicability);
|
||||
diag.span_suggestion(e.span, "try", suggestion, applicability);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NeedlessParensOnRangeLiterals {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let Some(higher::Range { start, end, .. }) = higher::Range::hir(expr) {
|
||||
if let Some(start) = start {
|
||||
check_for_parens(cx, start, true);
|
||||
}
|
||||
if let Some(end) = end {
|
||||
check_for_parens(cx, end, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![warn(clippy::almost_complete_letter_range)]
|
||||
#![allow(ellipsis_inclusive_range_patterns)]
|
||||
#![allow(clippy::needless_parens_on_range_literals)]
|
||||
|
||||
macro_rules! a {
|
||||
() => {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![warn(clippy::almost_complete_letter_range)]
|
||||
#![allow(ellipsis_inclusive_range_patterns)]
|
||||
#![allow(clippy::needless_parens_on_range_literals)]
|
||||
|
||||
macro_rules! a {
|
||||
() => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:19:17
|
||||
--> $DIR/almost_complete_letter_range.rs:20:17
|
||||
|
|
||||
LL | let _ = ('a') ..'z';
|
||||
| ^^^^^^--^^^
|
||||
@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z';
|
||||
= note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:20:17
|
||||
--> $DIR/almost_complete_letter_range.rs:21:17
|
||||
|
|
||||
LL | let _ = 'A' .. ('Z');
|
||||
| ^^^^--^^^^^^
|
||||
@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z');
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:26:13
|
||||
--> $DIR/almost_complete_letter_range.rs:27:13
|
||||
|
|
||||
LL | let _ = (b'a')..(b'z');
|
||||
| ^^^^^^--^^^^^^
|
||||
@ -25,7 +25,7 @@ LL | let _ = (b'a')..(b'z');
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:27:13
|
||||
--> $DIR/almost_complete_letter_range.rs:28:13
|
||||
|
|
||||
LL | let _ = b'A'..b'Z';
|
||||
| ^^^^--^^^^
|
||||
@ -33,7 +33,7 @@ LL | let _ = b'A'..b'Z';
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:32:13
|
||||
--> $DIR/almost_complete_letter_range.rs:33:13
|
||||
|
|
||||
LL | let _ = a!()..'z';
|
||||
| ^^^^--^^^
|
||||
@ -41,7 +41,7 @@ LL | let _ = a!()..'z';
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:35:9
|
||||
--> $DIR/almost_complete_letter_range.rs:36:9
|
||||
|
|
||||
LL | b'a'..b'z' if true => 1,
|
||||
| ^^^^--^^^^
|
||||
@ -49,7 +49,7 @@ LL | b'a'..b'z' if true => 1,
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:36:9
|
||||
--> $DIR/almost_complete_letter_range.rs:37:9
|
||||
|
|
||||
LL | b'A'..b'Z' if true => 2,
|
||||
| ^^^^--^^^^
|
||||
@ -57,7 +57,7 @@ LL | b'A'..b'Z' if true => 2,
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:43:9
|
||||
--> $DIR/almost_complete_letter_range.rs:44:9
|
||||
|
|
||||
LL | 'a'..'z' if true => 1,
|
||||
| ^^^--^^^
|
||||
@ -65,7 +65,7 @@ LL | 'a'..'z' if true => 1,
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:44:9
|
||||
--> $DIR/almost_complete_letter_range.rs:45:9
|
||||
|
|
||||
LL | 'A'..'Z' if true => 2,
|
||||
| ^^^--^^^
|
||||
@ -73,7 +73,7 @@ LL | 'A'..'Z' if true => 2,
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:54:9
|
||||
--> $DIR/almost_complete_letter_range.rs:55:9
|
||||
|
|
||||
LL | 'a'..'z' => 1,
|
||||
| ^^^--^^^
|
||||
@ -81,7 +81,7 @@ LL | 'a'..'z' => 1,
|
||||
| help: use an inclusive range: `...`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:61:13
|
||||
--> $DIR/almost_complete_letter_range.rs:62:13
|
||||
|
|
||||
LL | let _ = 'a'..'z';
|
||||
| ^^^--^^^
|
||||
@ -89,7 +89,7 @@ LL | let _ = 'a'..'z';
|
||||
| help: use an inclusive range: `..=`
|
||||
|
||||
error: almost complete ascii letter range
|
||||
--> $DIR/almost_complete_letter_range.rs:63:9
|
||||
--> $DIR/almost_complete_letter_range.rs:64:9
|
||||
|
|
||||
LL | 'a'..'z' => 1,
|
||||
| ^^^--^^^
|
||||
|
14
tests/ui/needless_parens_on_range_literals.fixed
Normal file
14
tests/ui/needless_parens_on_range_literals.fixed
Normal file
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
// edition:2018
|
||||
|
||||
#![warn(clippy::needless_parens_on_range_literals)]
|
||||
#![allow(clippy::almost_complete_letter_range)]
|
||||
|
||||
fn main() {
|
||||
let _ = 'a'..='z';
|
||||
let _ = 'a'..'z';
|
||||
let _ = (1.)..2.;
|
||||
let _ = (1.)..2.;
|
||||
let _ = 'a'..;
|
||||
let _ = ..'z';
|
||||
}
|
14
tests/ui/needless_parens_on_range_literals.rs
Normal file
14
tests/ui/needless_parens_on_range_literals.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
// edition:2018
|
||||
|
||||
#![warn(clippy::needless_parens_on_range_literals)]
|
||||
#![allow(clippy::almost_complete_letter_range)]
|
||||
|
||||
fn main() {
|
||||
let _ = ('a')..=('z');
|
||||
let _ = 'a'..('z');
|
||||
let _ = (1.)..2.;
|
||||
let _ = (1.)..(2.);
|
||||
let _ = ('a')..;
|
||||
let _ = ..('z');
|
||||
}
|
40
tests/ui/needless_parens_on_range_literals.stderr
Normal file
40
tests/ui/needless_parens_on_range_literals.stderr
Normal file
@ -0,0 +1,40 @@
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:8:13
|
||||
|
|
||||
LL | let _ = ('a')..=('z');
|
||||
| ^^^^^ help: try: `'a'`
|
||||
|
|
||||
= note: `-D clippy::needless-parens-on-range-literals` implied by `-D warnings`
|
||||
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:8:21
|
||||
|
|
||||
LL | let _ = ('a')..=('z');
|
||||
| ^^^^^ help: try: `'z'`
|
||||
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:9:18
|
||||
|
|
||||
LL | let _ = 'a'..('z');
|
||||
| ^^^^^ help: try: `'z'`
|
||||
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:11:19
|
||||
|
|
||||
LL | let _ = (1.)..(2.);
|
||||
| ^^^^ help: try: `2.`
|
||||
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:12:13
|
||||
|
|
||||
LL | let _ = ('a')..;
|
||||
| ^^^^^ help: try: `'a'`
|
||||
|
||||
error: needless parenthesis on range literals can be removed
|
||||
--> $DIR/needless_parens_on_range_literals.rs:13:15
|
||||
|
|
||||
LL | let _ = ..('z');
|
||||
| ^^^^^ help: try: `'z'`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user