Skip to content

Commit 4713ffa

Browse files
committed
resolve issue #812
1 parent 57cbadd commit 4713ffa

File tree

4 files changed

+102
-2
lines changed

4 files changed

+102
-2
lines changed

clippy_lints/src/collapsible_if.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_config::Conf;
2+
use clippy_utils::SpanlessEq;
23
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
34
use clippy_utils::msrvs::{self, Msrv};
45
use clippy_utils::source::{IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability};
@@ -163,6 +164,54 @@ impl CollapsibleIf {
163164
}
164165
}
165166

167+
fn check_collapsible_if_nested_if_else(context: &LateContext<'_>, if_expr: &Expr<'_>) {
168+
let ExprKind::If(cond, then, else_opt) = if_expr.kind else {
169+
return;
170+
};
171+
172+
let ExprKind::Block(then_block, _) = then.kind else {
173+
return;
174+
};
175+
176+
let Some(then_expr) = then_block.expr else {
177+
return;
178+
};
179+
180+
let ExprKind::If(inner_cond, inner_then, inner_else_opt) = then_expr.kind else {
181+
return;
182+
};
183+
184+
let Some(else_expr) = else_opt else {
185+
return;
186+
};
187+
188+
let mut spanless_eq = SpanlessEq::new(context);
189+
190+
if !spanless_eq.eq_expr(inner_then, else_expr) {
191+
return;
192+
}
193+
194+
span_lint_and_then(
195+
context,
196+
COLLAPSIBLE_IF,
197+
if_expr.span,
198+
"this `if` statement can be collapsed.",
199+
|diag| {
200+
diag.span_suggestion(
201+
if_expr.span,
202+
"collapse else and nested if blocks",
203+
format!(
204+
"if !{} || {} {}",
205+
cond.span.get_source_text(context).unwrap().to_owned(),
206+
inner_cond.span.get_source_text(context).unwrap().to_owned(),
207+
else_expr.span.get_source_text(context).unwrap().to_owned()
208+
),
209+
Applicability::MachineApplicable
210+
);
211+
},
212+
);
213+
}
214+
166215
fn eligible_condition(&self, cx: &LateContext<'_>, cond: &Expr<'_>) -> bool {
167216
!matches!(cond.kind, ExprKind::Let(..))
168217
|| (cx.tcx.sess.edition().at_least_rust_2024() && self.msrv.meets(cx, msrvs::LET_CHAINS))
@@ -180,6 +229,8 @@ impl LateLintPass<'_> for CollapsibleIf {
180229
&& let ExprKind::Block(else_, None) = else_.kind
181230
{
182231
Self::check_collapsible_else_if(cx, then.span, else_);
232+
233+
Self::check_collapsible_if_nested_if_else(cx, expr);
183234
} else if else_.is_none()
184235
&& self.eligible_condition(cx, cond)
185236
&& let ExprKind::Block(then, None) = then.kind

tests/ui/collapsible_if.fixed

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,19 @@ fn main() {
132132
println!("Hello world!");
133133
}
134134
}
135+
136+
let a = false;
137+
138+
let b = false;
139+
140+
if !a || b {
141+
println!("Hello world!");
142+
}
143+
//~^^^^^^^^ collapsible_if
144+
145+
if !a || b {
146+
println!("Hello world!");
147+
}
135148
}
136149

137150
#[rustfmt::skip]

tests/ui/collapsible_if.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,24 @@ fn main() {
142142
println!("Hello world!");
143143
}
144144
}
145+
146+
let a = false;
147+
148+
let b = false;
149+
150+
if a {
151+
if b {
152+
println!("Hello world!");
153+
}
154+
}
155+
else {
156+
println!("Hello world!");
157+
}
158+
//~^^^^^^^^ collapsible_if
159+
160+
if !a || b {
161+
println!("Hello world!");
162+
}
145163
}
146164

147165
#[rustfmt::skip]

tests/ui/collapsible_if.stderr

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,26 @@ LL | println!("No comment, linted");
172172
LL ~ }
173173
|
174174

175+
error: this `if` statement can be collapsed.
176+
--> tests/ui/collapsible_if.rs:150:5
177+
|
178+
LL | / if a {
179+
LL | | if b {
180+
LL | | println!("Hello world!");
181+
... |
182+
LL | | println!("Hello world!");
183+
LL | | }
184+
| |_____^
185+
|
186+
help: collapse else and nested if blocks
187+
|
188+
LL ~ if !a || b {
189+
LL + println!("Hello world!");
190+
LL + }
191+
|
192+
175193
error: this `if` statement can be collapsed
176-
--> tests/ui/collapsible_if.rs:149:5
194+
--> tests/ui/collapsible_if.rs:167:5
177195
|
178196
LL | / if true {
179197
LL | | if true {
@@ -190,5 +208,5 @@ LL | // This is a comment, do not collapse code to it
190208
LL ~ ; 3
191209
|
192210

193-
error: aborting due to 11 previous errors
211+
error: aborting due to 12 previous errors
194212

0 commit comments

Comments
 (0)