Merge pull request #1465 from Manishearth/1464

Use `span_suggestion` in the `precedence` lint
This commit is contained in:
llogiq 2017-01-22 16:32:37 +01:00 committed by GitHub
commit bc497a6262
2 changed files with 54 additions and 35 deletions

View File

@ -1,7 +1,7 @@
use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::Spanned;
use utils::{span_lint, snippet};
use utils::{span_lint_and_then, snippet};
/// **What it does:** Checks for operations where precedence may be unclear
/// and suggests to add parentheses. Currently it catches the following:
@ -36,41 +36,39 @@ fn get_lints(&self) -> LintArray {
impl EarlyLintPass for Precedence {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.node {
let span_sugg =
|expr: &Expr, sugg| {
span_lint_and_then(cx, PRECEDENCE, expr.span, "operator precedence can trip the unwary", |db| {
db.span_suggestion(expr.span, "consider parenthesizing your expression", sugg);
});
};
if !is_bit_op(op) {
return;
}
match (is_arith_expr(left), is_arith_expr(right)) {
(true, true) => {
span_lint(cx,
PRECEDENCE,
expr.span,
&format!("operator precedence can trip the unwary. Consider parenthesizing your \
expression:`({}) {} ({})`",
let sugg = format!("({}) {} ({})",
snippet(cx, left.span, ".."),
op.to_string(),
snippet(cx, right.span, "..")));
snippet(cx, right.span, ".."));
span_sugg(expr, sugg);
},
(true, false) => {
span_lint(cx,
PRECEDENCE,
expr.span,
&format!("operator precedence can trip the unwary. Consider parenthesizing your \
expression:`({}) {} {}`",
let sugg = format!("({}) {} {}",
snippet(cx, left.span, ".."),
op.to_string(),
snippet(cx, right.span, "..")));
snippet(cx, right.span, ".."));
span_sugg(expr, sugg);
},
(false, true) => {
span_lint(cx,
PRECEDENCE,
expr.span,
&format!("operator precedence can trip the unwary. Consider parenthesizing your \
expression:`{} {} ({})`",
let sugg = format!("{} {} ({})",
snippet(cx, left.span, ".."),
op.to_string(),
snippet(cx, right.span, "..")));
snippet(cx, right.span, ".."));
span_sugg(expr, sugg);
},
_ => (),
(false, false) => (),
}
}
@ -82,12 +80,15 @@ fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
LitKind::Int(..) |
LitKind::Float(..) |
LitKind::FloatUnsuffixed(..) => {
span_lint(cx,
PRECEDENCE,
expr.span,
&format!("unary minus has lower precedence than method call. Consider \
adding parentheses to clarify your intent: -({})",
snippet(cx, rhs.span, "..")));
span_lint_and_then(cx,
PRECEDENCE,
expr.span,
"unary minus has lower precedence than method call",
|db| {
db.span_suggestion(expr.span,
"consider adding parentheses to clarify your intent",
format!("-({})", snippet(cx, rhs.span, "..")));
});
},
_ => (),
}

View File

@ -5,16 +5,34 @@
#[allow(identity_op)]
#[allow(eq_op)]
fn main() {
format!("{} vs. {}", 1 << 2 + 3, (1 << 2) + 3); //~ERROR operator precedence can trip
format!("{} vs. {}", 1 + 2 << 3, 1 + (2 << 3)); //~ERROR operator precedence can trip
format!("{} vs. {}", 4 >> 1 + 1, (4 >> 1) + 1); //~ERROR operator precedence can trip
format!("{} vs. {}", 1 + 3 >> 2, 1 + (3 >> 2)); //~ERROR operator precedence can trip
format!("{} vs. {}", 1 ^ 1 - 1, (1 ^ 1) - 1); //~ERROR operator precedence can trip
format!("{} vs. {}", 3 | 2 - 1, (3 | 2) - 1); //~ERROR operator precedence can trip
format!("{} vs. {}", 3 & 5 - 2, (3 & 5) - 2); //~ERROR operator precedence can trip
1 << 2 + 3;
//~^ ERROR operator precedence can trip
//~| SUGGESTION 1 << (2 + 3)
1 + 2 << 3;
//~^ERROR operator precedence can trip
//~| SUGGESTION (1 + 2) << 3
4 >> 1 + 1;
//~^ERROR operator precedence can trip
//~| SUGGESTION 4 >> (1 + 1)
1 + 3 >> 2;
//~^ERROR operator precedence can trip
//~| SUGGESTION (1 + 3) >> 2
1 ^ 1 - 1;
//~^ERROR operator precedence can trip
//~| SUGGESTION 1 ^ (1 - 1)
3 | 2 - 1;
//~^ERROR operator precedence can trip
//~| SUGGESTION 3 | (2 - 1)
3 & 5 - 2;
//~^ERROR operator precedence can trip
//~| SUGGESTION 3 & (5 - 2)
format!("{} vs. {}", -1i32.abs(), (-1i32).abs()); //~ERROR unary minus has lower precedence
format!("{} vs. {}", -1f32.abs(), (-1f32).abs()); //~ERROR unary minus has lower precedence
-1i32.abs();
//~^ERROR unary minus has lower precedence
//~| SUGGESTION -(1i32.abs())
-1f32.abs();
//~^ERROR unary minus has lower precedence
//~| SUGGESTION -(1f32.abs())
// These should not trigger an error
let _ = (-1i32).abs();