Skip to content

Commit dbf6dc6

Browse files
committed
Add more sugggestion-building functions
1 parent 9bd7fa0 commit dbf6dc6

File tree

4 files changed

+73
-25
lines changed

4 files changed

+73
-25
lines changed

clippy_lints/src/collapsible_if.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ fn check_collapsible_no_if_let(
107107
db.span_suggestion(expr.span,
108108
"try",
109109
format!("if {} {}",
110-
lhs.and(&rhs),
110+
lhs.and(rhs),
111111
snippet_block(cx, content.span, "..")));
112112
});
113113
}}

clippy_lints/src/matches.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
263263
Some(format!("if {} {}", snippet(cx, ex.span, "b"), expr_block(cx, true_expr, None, "..")))
264264
}
265265
(true, false) => {
266-
let test = &Sugg::hir(cx, ex, "..");
266+
let test = Sugg::hir(cx, ex, "..");
267267
Some(format!("if {} {}",
268268
!test,
269269
expr_block(cx, false_expr, None, "..")))

clippy_lints/src/misc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl LateLintPass for TopLevelRefPass {
7272
l.pat.span,
7373
"`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
7474
|db| {
75-
let init = &Sugg::hir(cx, init, "..");
75+
let init = Sugg::hir(cx, init, "..");
7676
db.span_suggestion(s.span,
7777
"try",
7878
format!("let {}{} = {};",
@@ -171,8 +171,8 @@ impl LateLintPass for FloatCmp {
171171
expr.span,
172172
"strict comparison of f32 or f64",
173173
|db| {
174-
let lhs = &Sugg::hir(cx, left, "..");
175-
let rhs = &Sugg::hir(cx, right, "..");
174+
let lhs = Sugg::hir(cx, left, "..");
175+
let rhs = Sugg::hir(cx, right, "..");
176176

177177
db.span_suggestion(expr.span,
178178
"consider comparing them within some error",

clippy_lints/src/utils/sugg.rs

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std;
55
use syntax::ast;
66
use syntax::util::parser::AssocOp;
77
use utils::{higher, snippet};
8+
use syntax::print::pprust::binop_to_string;
89

910
/// A helper type to build suggestion correctly handling parenthesis.
1011
pub enum Sugg<'a> {
@@ -16,6 +17,9 @@ pub enum Sugg<'a> {
1617
BinOp(AssocOp, Cow<'a, str>),
1718
}
1819

20+
/// Literal constant `1`, for convenience.
21+
pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1"));
22+
1923
impl<'a> std::fmt::Display for Sugg<'a> {
2024
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
2125
match *self {
@@ -110,28 +114,43 @@ impl<'a> Sugg<'a> {
110114
}
111115
}
112116

113-
/// Convenience method to create the `lhs && rhs` suggestion.
114-
pub fn and(&self, rhs: &Self) -> Sugg<'static> {
115-
make_binop(ast::BinOpKind::And, self, rhs)
117+
/// Convenience method to create the `<lhs> && <rhs>` suggestion.
118+
pub fn and(self, rhs: Self) -> Sugg<'static> {
119+
make_binop(ast::BinOpKind::And, &self, &rhs)
116120
}
117121

118122
/// Convenience method to create the `&<expr>` suggestion.
119-
pub fn addr(&self) -> Sugg<'static> {
120-
make_unop("&", self)
123+
pub fn addr(self) -> Sugg<'static> {
124+
make_unop("&", &self)
125+
}
126+
127+
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion.
128+
pub fn range(self, end: Self, limit: ast::RangeLimits) -> Sugg<'static> {
129+
match limit {
130+
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, &end),
131+
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotDot, &self, &end),
132+
}
133+
}
134+
}
135+
136+
impl<'a, 'b> std::ops::Add<Sugg<'b>> for Sugg<'a> {
137+
type Output = Sugg<'static>;
138+
fn add(self, rhs: Sugg<'b>) -> Sugg<'static> {
139+
make_binop(ast::BinOpKind::Add, &self, &rhs)
121140
}
122141
}
123142

124-
impl<'a, 'b> std::ops::Sub<&'b Sugg<'b>> for &'a Sugg<'a> {
143+
impl<'a, 'b> std::ops::Sub<Sugg<'b>> for Sugg<'a> {
125144
type Output = Sugg<'static>;
126-
fn sub(self, rhs: &'b Sugg<'b>) -> Sugg<'static> {
127-
make_binop(ast::BinOpKind::Sub, self, rhs)
145+
fn sub(self, rhs: Sugg<'b>) -> Sugg<'static> {
146+
make_binop(ast::BinOpKind::Sub, &self, &rhs)
128147
}
129148
}
130149

131-
impl<'a> std::ops::Not for &'a Sugg<'a> {
150+
impl<'a> std::ops::Not for Sugg<'a> {
132151
type Output = Sugg<'static>;
133152
fn not(self) -> Sugg<'static> {
134-
make_unop("!", self)
153+
make_unop("!", &self)
135154
}
136155
}
137156

@@ -172,7 +191,7 @@ pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> {
172191
///
173192
/// Precedence of shift operator relative to other arithmetic operation is often confusing so
174193
/// parenthesis will always be added for a mix of these.
175-
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> {
194+
pub fn make_assoc(op: AssocOp, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> {
176195
fn is_shift(op: &AssocOp) -> bool {
177196
matches!(*op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
178197
}
@@ -190,25 +209,54 @@ pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> {
190209
is_shift(other) && is_arith(op)
191210
}
192211

193-
let aop = AssocOp::from_ast_binop(op);
194-
195212
let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs {
196-
needs_paren(&aop, lop, Associativity::Left)
213+
needs_paren(&op, lop, Associativity::Left)
197214
} else {
198215
false
199216
};
200217

201218
let rhs_paren = if let Sugg::BinOp(ref rop, _) = *rhs {
202-
needs_paren(&aop, rop, Associativity::Right)
219+
needs_paren(&op, rop, Associativity::Right)
203220
} else {
204221
false
205222
};
206223

207-
Sugg::BinOp(aop,
208-
format!("{} {} {}",
209-
ParenHelper::new(lhs_paren, lhs),
210-
op.to_string(),
211-
ParenHelper::new(rhs_paren, rhs)).into())
224+
let lhs = ParenHelper::new(lhs_paren, lhs);
225+
let rhs = ParenHelper::new(rhs_paren, rhs);
226+
let sugg = match op {
227+
AssocOp::Add |
228+
AssocOp::BitAnd |
229+
AssocOp::BitOr |
230+
AssocOp::BitXor |
231+
AssocOp::Divide |
232+
AssocOp::Equal |
233+
AssocOp::Greater |
234+
AssocOp::GreaterEqual |
235+
AssocOp::LAnd |
236+
AssocOp::LOr |
237+
AssocOp::Less |
238+
AssocOp::LessEqual |
239+
AssocOp::Modulus |
240+
AssocOp::Multiply |
241+
AssocOp::NotEqual |
242+
AssocOp::ShiftLeft |
243+
AssocOp::ShiftRight |
244+
AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs),
245+
AssocOp::Inplace => format!("in ({}) {}", lhs, rhs),
246+
AssocOp::Assign => format!("{} = {}", lhs, rhs),
247+
AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, binop_to_string(op), rhs),
248+
AssocOp::As => format!("{} as {}", lhs, rhs),
249+
AssocOp::DotDot => format!("{}..{}", lhs, rhs),
250+
AssocOp::DotDotDot => format!("{}...{}", lhs, rhs),
251+
AssocOp::Colon => format!("{}: {}", lhs, rhs),
252+
};
253+
254+
Sugg::BinOp(op, sugg.into())
255+
}
256+
257+
/// Convinience wrapper arround `make_assoc` and `AssocOp::from_ast_binop`.
258+
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg, rhs: &Sugg) -> Sugg<'static> {
259+
make_assoc(AssocOp::from_ast_binop(op), lhs, rhs)
212260
}
213261

214262
#[derive(PartialEq, Eq)]

0 commit comments

Comments
 (0)