Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 90c8463

Browse files
committed
Rewrite check to account for floating point literals
1 parent 5948959 commit 90c8463

File tree

5 files changed

+61
-22
lines changed

5 files changed

+61
-22
lines changed

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
747747
store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
748748
store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements));
749749
store.register_early_pass(|| Box::new(precedence::Precedence));
750-
store.register_early_pass(|| Box::new(needless_parens_on_range_literal::NeedlessParensOnRangeLiteral));
750+
store.register_late_pass(|| Box::new(needless_parens_on_range_literal::NeedlessParensOnRangeLiteral));
751751
store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue));
752752
store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
753753
store.register_late_pass(|| Box::new(create_dir::CreateDir));

clippy_lints/src/needless_parens_on_range_literal.rs

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,17 @@
1717
//! ```
1818
//!
1919
20-
use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt};
21-
use rustc_ast::ast::{Expr, ExprKind};
20+
use clippy_utils::{
21+
diagnostics::span_lint_and_then,
22+
higher,
23+
source::{snippet, snippet_opt},
24+
};
25+
26+
use rustc_ast::ast;
2227
use rustc_errors::Applicability;
23-
use rustc_lint::{EarlyContext, EarlyLintPass};
28+
use rustc_hir::{Expr, ExprKind};
29+
30+
use rustc_lint::{LateContext, LateLintPass};
2431
use rustc_session::{declare_lint_pass, declare_tool_lint};
2532

2633
declare_clippy_lint! {
@@ -40,27 +47,47 @@ declare_clippy_lint! {
4047

4148
declare_lint_pass!(NeedlessParensOnRangeLiteral => [NEEDLESS_PARENS_ON_RANGE_LITERAL]);
4249

43-
fn check_for_parens(cx: &EarlyContext<'_>, e: &Expr) {
44-
if_chain! {
45-
if let ExprKind::Paren(ref start_statement) = &e.kind;
46-
if let ExprKind::Lit(ref literal) = start_statement.kind;
47-
then {
48-
span_lint_and_then(cx, NEEDLESS_PARENS_ON_RANGE_LITERAL, e.span,
49-
"needless parenthesis on range literal can be removed",
50-
|diag| {
51-
if let Some(suggestion) = snippet_opt(cx, literal.span) {
52-
diag.span_suggestion(e.span, "try", suggestion, Applicability::MachineApplicable);
53-
}
54-
});
50+
fn snippet_enclosed_in_parenthesis(snippet: &str) -> bool {
51+
snippet.starts_with('(') && snippet.ends_with(')')
52+
}
53+
54+
fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) {
55+
if is_start &&
56+
let ExprKind::Lit(ref literal) = e.kind &&
57+
let ast::LitKind::Float(_sym, ast::LitFloatType::Unsuffixed) = literal.node
58+
{
59+
// don't check floating point literals on the start expression of a range
60+
return;
5561
}
62+
if_chain! {
63+
if let ExprKind::Lit(ref literal) = e.kind;
64+
// the indicator that paranthese surround the literal is that span of the expression and the literal differ
65+
if (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo);
66+
// inspect the source code of the expression for parenthesis
67+
if snippet_enclosed_in_parenthesis(&snippet(cx, e.span, ""));
68+
then {
69+
span_lint_and_then(cx, NEEDLESS_PARENS_ON_RANGE_LITERAL, e.span,
70+
"needless parenthesis on range literal can be removed",
71+
|diag| {
72+
if let Some(suggestion) = snippet_opt(cx, literal.span) {
73+
diag.span_suggestion(e.span, "try", suggestion, Applicability::MachineApplicable);
74+
}
75+
});
76+
}
5677
}
5778
}
5879

59-
impl EarlyLintPass for NeedlessParensOnRangeLiteral {
60-
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
61-
if let ExprKind::Range(Some(start), Some(end), _) = &e.kind {
62-
check_for_parens(cx, start);
63-
check_for_parens(cx, end);
80+
impl<'tcx> LateLintPass<'tcx> for NeedlessParensOnRangeLiteral {
81+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
82+
// if let higher::Range { start, end, limits } = &e.kind {
83+
if let Some(higher::Range {
84+
start: Some(start),
85+
end: Some(end),
86+
..
87+
}) = higher::Range::hir(expr)
88+
{
89+
check_for_parens(cx, start, true);
90+
check_for_parens(cx, end, false);
6491
}
6592
}
6693
}

tests/ui/needless_parens_on_range_literal.fixed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66

77
fn main() {
88
let _ = 'a'..='z';
9+
let _ = 'a'..='z';
10+
let _ = (1.)..2.;
11+
let _ = (1.)..2.;
912
}

tests/ui/needless_parens_on_range_literal.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66

77
fn main() {
88
let _ = ('a')..=('z');
9+
let _ = 'a'..='z';
10+
let _ = (1.)..2.;
11+
let _ = (1.)..(2.);
912
}

tests/ui/needless_parens_on_range_literal.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,11 @@ error: needless parenthesis on range literal can be removed
1212
LL | let _ = ('a')..=('z');
1313
| ^^^^^ help: try: `'z'`
1414

15-
error: aborting due to 2 previous errors
15+
error: needless parenthesis on range literal can be removed
16+
--> $DIR/needless_parens_on_range_literal.rs:11:19
17+
|
18+
LL | let _ = (1.)..(2.);
19+
| ^^^^ help: try: `2.`
20+
21+
error: aborting due to 3 previous errors
1622

0 commit comments

Comments
 (0)