Skip to content

Commit ad6b9e2

Browse files
committed
more comments, implement UnOp::Not
1 parent 4154749 commit ad6b9e2

4 files changed

Lines changed: 75 additions & 7 deletions

File tree

clippy_lints/src/assert_multiple.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::macros::{find_assert_args, root_macro_call_first_node};
33
use clippy_utils::source::snippet;
44
use rustc_errors::Applicability;
55
use rustc_hir::intravisit::Visitor;
6-
use rustc_hir::{BinOpKind, Expr, ExprKind};
6+
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::declare_lint_pass;
99
use rustc_span::sym;
@@ -40,6 +40,9 @@ declare_clippy_lint! {
4040

4141
declare_lint_pass!(AssertMultiple => [ASSERT_MULTIPLE]);
4242

43+
// This visiior is a convenient place to hold the session context, as well as the collection of
44+
// replacement strings and the type of assert to use.
45+
4346
struct AssertVisitor<'tcx, 'v> {
4447
cx: &'v LateContext<'tcx>,
4548
suggests: Vec<String>,
@@ -51,37 +54,47 @@ impl<'tcx> Visitor<'tcx> for AssertVisitor<'tcx, '_> {
5154
match e.kind {
5255
ExprKind::Binary(op, lhs, rhs) => match op.node {
5356
BinOpKind::And => {
57+
// For And, turn each of the rhs and lhs expressions into their own assert.
5458
rustc_hir::intravisit::walk_expr(self, lhs);
5559
rustc_hir::intravisit::walk_expr(self, rhs);
5660
},
5761
BinOpKind::Or => {
62+
// For Or, we cannot break the expression up.
5863
let tmpstr = format!("{}!{};", self.assert_string, snippet(self.cx, e.span, ".."));
5964
self.suggests.push(tmpstr);
6065
},
6166
_ => {
6267
if let Some(x) = assert_from_op(self, op.node, *lhs, *rhs) {
68+
// handle most of the binary operators here.
6369
self.suggests.push(x);
6470
}
6571
},
6672
},
6773
ExprKind::Call(_call, _args) => {
74+
// split function calls into their own assert.
6875
let tmptxt = snippet(self.cx, e.span, "..");
69-
let tmpassrt = format!("{}!({});", self.assert_string, tmptxt.trim_end_matches(';'));
76+
let tmpassrt = format!("{}!({});", self.assert_string, tmptxt);
7077
self.suggests.push(tmpassrt);
7178
},
7279

7380
ExprKind::MethodCall(_path, expr, _args, span) => {
81+
// split method calls into their own assert as well.
7482
let calltext = snippet(self.cx, expr.span, "..");
75-
7683
let tmptxt = format!("{}.{};", &*calltext, snippet(self.cx, span, ".."));
7784
self.suggests.push(tmptxt);
7885
},
7986
ExprKind::Path(qpath) => {
80-
// this is a boolean variable
87+
// this is a statndalone boolean variable, not an expression.
8188
let name = snippet(self.cx, qpath.span(), "_");
8289
let tmptxt = format!("{}!({name});", self.assert_string);
8390
self.suggests.push(tmptxt);
8491
},
92+
ExprKind::Unary(UnOp::Not, expr) => {
93+
// A Not operator, just output the
94+
let exptext = snippet(self.cx, expr.span, "_");
95+
let tmptxt = format!("{}!(!{exptext});", self.assert_string);
96+
self.suggests.push(tmptxt);
97+
},
8598

8699
_ => {},
87100
}
@@ -99,6 +112,8 @@ impl<'tcx> LateLintPass<'tcx> for AssertMultiple {
99112
&& let Some((condition, _)) = find_assert_args(cx, e, macro_call.expn)
100113
&& matches!(condition.kind, ExprKind::Binary(binop,_lhs,_rhs) if binop.node == BinOpKind::And)
101114
{
115+
// We only get here on assert/debug_assert macro calls whose arguments have an And expression
116+
// on the top of the tree.
102117
let mut am_visitor = AssertVisitor {
103118
cx,
104119
suggests: Vec::new(),
@@ -122,6 +137,8 @@ impl<'tcx> LateLintPass<'tcx> for AssertMultiple {
122137
}
123138
}
124139

140+
// This function separates out a binary operation into a separate assert, using ..._eq or ..._ne if
141+
// applicable.
125142
fn assert_from_op(
126143
visitor: &mut AssertVisitor<'_, '_>,
127144
node: BinOpKind,

tests/ui/assert_multiple.fixed

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,17 @@ fn main() {
5757
assert_eq!(o, b);
5858
assert!(is_bool);
5959
//~^ assert_multiple
60+
assert!(!is_bool);
61+
assert_eq!(o, b);
62+
//~^ assert_multiple
63+
assert_eq!(o, b);
64+
assert!(!is_bool);
65+
//~^ assert_multiple
66+
assert_eq!(o, b);
67+
assert!(!(is_bool && o == Vals::Owned));
68+
//~^ assert_multiple
6069

61-
// Next one we cannot split because of Or.
70+
// Next ones we cannot split.
6271
assert!((o == b && o == Vals::Owned) || b == Vals::Other);
6372
assert!(o == Vals::Owned || b == Vals::Other);
6473
debug_assert!(o == b);

tests/ui/assert_multiple.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ fn main() {
5151
//~^ assert_multiple
5252
assert!(o == b && is_bool);
5353
//~^ assert_multiple
54+
assert!(!is_bool && o == b);
55+
//~^ assert_multiple
56+
assert!(o == b && !is_bool);
57+
//~^ assert_multiple
58+
assert!(o == b && !(is_bool && o == Vals::Owned));
59+
//~^ assert_multiple
5460

55-
// Next one we cannot split because of Or.
61+
// Next ones we cannot split.
5662
assert!((o == b && o == Vals::Owned) || b == Vals::Other);
5763
assert!(o == Vals::Owned || b == Vals::Other);
5864
debug_assert!(o == b);

tests/ui/assert_multiple.stderr

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,41 @@ LL ~ assert_eq!(o, b);
7272
LL ~ assert!(is_bool);
7373
|
7474

75-
error: aborting due to 6 previous errors
75+
error: multiple asserts combined into one
76+
--> tests/ui/assert_multiple.rs:54:5
77+
|
78+
LL | assert!(!is_bool && o == b);
79+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
80+
|
81+
help: consider writing
82+
|
83+
LL ~ assert!(!is_bool);
84+
LL ~ assert_eq!(o, b);
85+
|
86+
87+
error: multiple asserts combined into one
88+
--> tests/ui/assert_multiple.rs:56:5
89+
|
90+
LL | assert!(o == b && !is_bool);
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
92+
|
93+
help: consider writing
94+
|
95+
LL ~ assert_eq!(o, b);
96+
LL ~ assert!(!is_bool);
97+
|
98+
99+
error: multiple asserts combined into one
100+
--> tests/ui/assert_multiple.rs:58:5
101+
|
102+
LL | assert!(o == b && !(is_bool && o == Vals::Owned));
103+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104+
|
105+
help: consider writing
106+
|
107+
LL ~ assert_eq!(o, b);
108+
LL ~ assert!(!(is_bool && o == Vals::Owned));
109+
|
110+
111+
error: aborting due to 9 previous errors
76112

0 commit comments

Comments
 (0)