Skip to content

Commit 21e9a12

Browse files
author
Michael Recachinas
committed
Use span_lint_and_then as per feedback
1 parent bb40bd6 commit 21e9a12

File tree

2 files changed

+106
-26
lines changed

2 files changed

+106
-26
lines changed

clippy_lints/src/int_plus_one.rs

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use rustc::lint::*;
44
use syntax::ast::*;
55

6-
use utils::span_help_and_lint;
6+
use utils::{span_lint_and_then, snippet_opt};
77

88
/// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block
99
///
@@ -45,6 +45,11 @@ impl LintPass for IntPlusOne {
4545
// x + 1 <= y
4646
// x <= y - 1
4747

48+
enum Side {
49+
LHS,
50+
RHS,
51+
}
52+
4853
impl IntPlusOne {
4954
#[allow(cast_sign_loss)]
5055
fn check_lit(&self, lit: &Lit, target_value: i128) -> bool {
@@ -54,62 +59,125 @@ impl IntPlusOne {
5459
false
5560
}
5661

57-
fn check_binop(&self, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> bool {
62+
fn check_binop(&self, cx: &EarlyContext, block: &Expr, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<(bool, Option<String>)> {
5863
match (binop, &lhs.node, &rhs.node) {
5964
// case where `x - 1 >= ...` or `-1 + x >= ...`
6065
(BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
6166
match (lhskind.node, &lhslhs.node, &lhsrhs.node) {
6267
// `-1 + x`
63-
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1),
68+
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) => {
69+
let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS);
70+
if self.check_lit(lit, -1) {
71+
self.emit_warning(cx, block, recommendation)
72+
}
73+
},
6474
// `x - 1`
65-
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1),
66-
_ => false
75+
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => {
76+
let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS);
77+
if self.check_lit(lit, 1) {
78+
self.emit_warning(cx, block, recommendation)
79+
}
80+
}
81+
_ => ()
6782
}
6883
},
6984
// case where `... >= y + 1` or `... >= 1 + y`
7085
(BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) if rhskind.node == BinOpKind::Add => {
7186
match (&rhslhs.node, &rhsrhs.node) {
7287
// `y + 1` and `1 + y`
73-
(&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1),
74-
_ => false
88+
(&ExprKind::Lit(ref lit), _) => {
89+
let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS);
90+
if self.check_lit(lit, 1) {
91+
self.emit_warning(cx, block, recommendation)
92+
}
93+
},
94+
(_, &ExprKind::Lit(ref lit)) => {
95+
let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS);
96+
if self.check_lit(lit, 1) {
97+
self.emit_warning(cx, block, recommendation)
98+
}
99+
},
100+
_ => ()
75101
}
76102
},
77103
// case where `x + 1 <= ...` or `1 + x <= ...`
78104
(BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => {
79105
match (&lhslhs.node, &lhsrhs.node) {
80106
// `1 + x` and `x + 1`
81-
(&ExprKind::Lit(ref lit), _)|(_, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1),
82-
_ => false
107+
(&ExprKind::Lit(ref lit), _) => {
108+
let recommendation = self.generate_recommendation(cx, binop, lhsrhs, rhs, Side::LHS);
109+
if self.check_lit(lit, 1) {
110+
self.emit_warning(cx, block, recommendation)
111+
}
112+
},
113+
(_, &ExprKind::Lit(ref lit)) => {
114+
let recommendation = self.generate_recommendation(cx, binop, lhslhs, rhs, Side::LHS);
115+
if self.check_lit(lit, 1) {
116+
self.emit_warning(cx, block, recommendation)
117+
}
118+
},
119+
_ => ()
83120
}
84121
},
85122
// case where `... >= y - 1` or `... >= -1 + y`
86123
(BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
87124
match (rhskind.node, &rhslhs.node, &rhsrhs.node) {
88125
// `-1 + y`
89-
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) => self.check_lit(lit, -1),
126+
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) => {
127+
let recommendation = self.generate_recommendation(cx, binop, rhsrhs, lhs, Side::RHS);
128+
if self.check_lit(lit, -1) {
129+
self.emit_warning(cx, block, recommendation)
130+
}
131+
},
90132
// `y - 1`
91-
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => self.check_lit(lit, 1),
92-
_ => false
133+
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) => {
134+
let recommendation = self.generate_recommendation(cx, binop, rhslhs, lhs, Side::RHS);
135+
if self.check_lit(lit, 1) {
136+
self.emit_warning(cx, block, recommendation)
137+
}
138+
},
139+
_ => ()
93140
}
94141
},
95-
_ => false
142+
_ => ()
96143
}
97144
}
98145

146+
fn generate_recommendation(&self, cx: &EarlyContext, binop: BinOpKind, node: &Expr, other_side: &Expr, side: Side) -> Option<String> {
147+
let binop_string = match binop {
148+
BinOpKind::Ge => ">",
149+
BinOpKind::Le => "<",
150+
_ => return None
151+
};
152+
if let Some(snippet) = snippet_opt(cx, node.span) {
153+
if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
154+
let rec = match side {
155+
Side::LHS => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)),
156+
Side::RHS => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)),
157+
};
158+
return rec;
159+
}
160+
}
161+
None
162+
}
163+
164+
fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: Option<String>) {
165+
if let Some(rec) = recommendation {
166+
span_lint_and_then(cx,
167+
INT_PLUS_ONE,
168+
block.span,
169+
"Unnecessary `>= y + 1` or `x - 1 >=`",
170+
|db| {
171+
db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", rec);
172+
});
173+
}
174+
}
99175
}
100176

101177
impl EarlyLintPass for IntPlusOne {
102178
fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) {
103179
if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node {
104-
if self.check_binop(kind.node, lhs, rhs) {
105-
span_help_and_lint(
106-
cx,
107-
INT_PLUS_ONE,
108-
item.span,
109-
"Unnecessary `>= y + 1` or `x - 1 >=`",
110-
"Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`",
111-
);
112-
}
180+
self.check_binop(cx, item, kind.node, lhs, rhs);
113181
}
114182
}
115183
}

tests/ui/int_plus_one.stderr

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,43 @@ error: Unnecessary `>= y + 1` or `x - 1 >=`
55
| ^^^^^^^^^^
66
|
77
= note: `-D int-plus-one` implied by `-D warnings`
8-
= help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`
8+
help: change `>= y + 1` to `> y` as shown
9+
|
10+
10 | x > y;
11+
| ^^^^^
912

1013
error: Unnecessary `>= y + 1` or `x - 1 >=`
1114
--> $DIR/int_plus_one.rs:11:5
1215
|
1316
11 | y + 1 <= x;
1417
| ^^^^^^^^^^
1518
|
16-
= help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`
19+
help: change `>= y + 1` to `> y` as shown
20+
|
21+
11 | y < x;
22+
| ^^^^^
1723

1824
error: Unnecessary `>= y + 1` or `x - 1 >=`
1925
--> $DIR/int_plus_one.rs:13:5
2026
|
2127
13 | x - 1 >= y;
2228
| ^^^^^^^^^^
2329
|
24-
= help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`
30+
help: change `>= y + 1` to `> y` as shown
31+
|
32+
13 | x > y;
33+
| ^^^^^
2534

2635
error: Unnecessary `>= y + 1` or `x - 1 >=`
2736
--> $DIR/int_plus_one.rs:14:5
2837
|
2938
14 | y <= x - 1;
3039
| ^^^^^^^^^^
3140
|
32-
= help: Consider reducing `x >= y + 1` or `x - 1 >= y` to `x > y`
41+
help: change `>= y + 1` to `> y` as shown
42+
|
43+
14 | y < x;
44+
| ^^^^^
3345

3446
error: aborting due to 4 previous errors
3547

0 commit comments

Comments
 (0)