Skip to content

Commit

Permalink
auto-fix for redundant_else lint
Browse files Browse the repository at this point in the history
  • Loading branch information
lapla-cogito committed Jan 3, 2025
1 parent 7a01033 commit 8ade7a6
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 25 deletions.
34 changes: 30 additions & 4 deletions clippy_lints/src/redundant_else.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet};
use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
use rustc_ast::visit::{Visitor, walk_expr};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
use rustc_span::Span;
use std::borrow::Cow;

declare_clippy_lint! {
/// ### What it does
Expand Down Expand Up @@ -77,13 +81,15 @@ impl EarlyLintPass for RedundantElse {
_ => break,
}
}
span_lint_and_help(

span_lint_and_sugg(
cx,
REDUNDANT_ELSE,
els.span,
els.span.with_lo(then.span.hi()),
"redundant else block",
None,
"remove the `else` block and move the contents out",
make_sugg(cx, els.span, "..", Some(expr.span)).to_string(),
Applicability::MachineApplicable,
);
}
}
Expand Down Expand Up @@ -138,3 +144,23 @@ impl BreakVisitor {
self.check(stmt, Self::visit_stmt)
}
}

// Extract the inner contents of an `else` block str
// e.g. `{ foo(); bar(); }` -> `foo(); bar();`
fn extract_else_block(mut block: &str) -> String {
block = block.strip_prefix("{").unwrap_or(block);
block = block.strip_suffix("}").unwrap_or(block);
block.trim_end().to_string()
}

fn make_sugg<'a>(
cx: &EarlyContext<'_>,
els_span: Span,
default: &'a str,
indent_relative_to: Option<Span>,
) -> Cow<'a, str> {
let extracted = extract_else_block(&snippet(cx, els_span, default));
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));

reindent_multiline(extracted.into(), false, indent)
}
154 changes: 154 additions & 0 deletions tests/ui/redundant_else.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#![warn(clippy::redundant_else)]
#![allow(clippy::needless_return, clippy::if_same_then_else, clippy::needless_late_init)]

fn main() {
loop {
// break
if foo() {
println!("Love your neighbor;");
break;
}
//~^ ERROR: redundant else block
println!("yet don't pull down your hedge.");
// continue
if foo() {
println!("He that lies down with Dogs,");
continue;
}
//~^ ERROR: redundant else block
println!("shall rise up with fleas.");
// match block
if foo() {
match foo() {
1 => break,
_ => return,
}
}
//~^ ERROR: redundant else block
println!("You may delay, but time will not.");
}
// else if
if foo() {
return;
} else if foo() {
return;
}
//~^ ERROR: redundant else block
println!("A fat kitchen makes a lean will.");
// let binding outside of block
let _ = {
if foo() {
return;
}
//~^ ERROR: redundant else block
1
};
// else if with let binding outside of block
let _ = {
if foo() {
return;
} else if foo() {
return;
}
//~^ ERROR: redundant else block
2
};
// inside if let
let _ = if let Some(1) = foo() {
let _ = 1;
if foo() {
return;
}
//~^ ERROR: redundant else block
1
} else {
1
};

//
// non-lint cases
//

// sanity check
if foo() {
let _ = 1;
} else {
println!("Who is wise? He that learns from every one.");
}
// else if without else
if foo() {
return;
} else if foo() {
foo()
};
// nested if return
if foo() {
if foo() {
return;
}
} else {
foo()
};
// match with non-breaking branch
if foo() {
match foo() {
1 => foo(),
_ => return,
}
} else {
println!("Three may keep a secret, if two of them are dead.");
}
// let binding
let _ = if foo() {
return;
} else {
1
};
// assign
let mut a;
a = if foo() {
return;
} else {
1
};
// assign-op
a += if foo() {
return;
} else {
1
};
// if return else if else
if foo() {
return;
} else if foo() {
1
} else {
2
};
// if else if return else
if foo() {
1
} else if foo() {
return;
} else {
2
};
// else if with let binding
let _ = if foo() {
return;
} else if foo() {
return;
} else {
2
};
// inside function call
Box::new(if foo() {
return;
} else {
1
});
}

fn foo<T>() -> T {
unimplemented!("I'm not Santa Claus")
}
77 changes: 56 additions & 21 deletions tests/ui/redundant_else.stderr
Original file line number Diff line number Diff line change
@@ -1,88 +1,123 @@
error: redundant else block
--> tests/ui/redundant_else.rs:10:16
--> tests/ui/redundant_else.rs:10:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | println!("yet don't pull down your hedge.");
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
= note: `-D clippy::redundant-else` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::redundant_else)]`
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + println!("yet don't pull down your hedge.");
|

error: redundant else block
--> tests/ui/redundant_else.rs:18:16
--> tests/ui/redundant_else.rs:18:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | println!("shall rise up with fleas.");
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + println!("shall rise up with fleas.");
|

error: redundant else block
--> tests/ui/redundant_else.rs:28:16
--> tests/ui/redundant_else.rs:28:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | println!("You may delay, but time will not.");
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + println!("You may delay, but time will not.");
|

error: redundant else block
--> tests/ui/redundant_else.rs:38:12
--> tests/ui/redundant_else.rs:38:6
|
LL | } else {
| ____________^
| ______^
LL | |
LL | | println!("A fat kitchen makes a lean will.");
LL | | }
| |_____^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + println!("A fat kitchen makes a lean will.");
|

error: redundant else block
--> tests/ui/redundant_else.rs:46:16
--> tests/ui/redundant_else.rs:46:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | 1
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + 1
|

error: redundant else block
--> tests/ui/redundant_else.rs:57:16
--> tests/ui/redundant_else.rs:57:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | 2
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + 2
|

error: redundant else block
--> tests/ui/redundant_else.rs:67:16
--> tests/ui/redundant_else.rs:67:10
|
LL | } else {
| ________________^
| __________^
LL | |
LL | | 1
LL | | }
| |_________^
|
= help: remove the `else` block and move the contents out
help: remove the `else` block and move the contents out
|
LL ~ }
LL +
LL + 1
|

error: aborting due to 7 previous errors

0 comments on commit 8ade7a6

Please sign in to comment.