13
13
//! This lint is **warn** by default
14
14
15
15
use clippy_utils:: diagnostics:: { span_lint_and_sugg, span_lint_and_then} ;
16
- use clippy_utils:: source:: { snippet_block, snippet_block_with_applicability} ;
16
+ use clippy_utils:: source:: { snippet , snippet_block, snippet_block_with_applicability} ;
17
17
use clippy_utils:: sugg:: Sugg ;
18
18
use if_chain:: if_chain;
19
19
use rustc_ast:: ast;
20
20
use rustc_errors:: Applicability ;
21
21
use rustc_lint:: { EarlyContext , EarlyLintPass } ;
22
22
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
23
+ use rustc_span:: Span ;
23
24
24
25
declare_clippy_lint ! {
25
26
/// ### What it does
@@ -102,7 +103,7 @@ impl EarlyLintPass for CollapsibleIf {
102
103
fn check_if ( cx : & EarlyContext < ' _ > , expr : & ast:: Expr ) {
103
104
if let ast:: ExprKind :: If ( check, then, else_) = & expr. kind {
104
105
if let Some ( else_) = else_ {
105
- check_collapsible_maybe_if_let ( cx, else_) ;
106
+ check_collapsible_maybe_if_let ( cx, then . span , else_) ;
106
107
} else if let ast:: ExprKind :: Let ( ..) = check. kind {
107
108
// Prevent triggering on `if let a = b { if c { .. } }`.
108
109
} else {
@@ -119,7 +120,7 @@ fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
119
120
trimmed_block_text. starts_with ( "//" ) || trimmed_block_text. starts_with ( "/*" )
120
121
}
121
122
122
- fn check_collapsible_maybe_if_let ( cx : & EarlyContext < ' _ > , else_ : & ast:: Expr ) {
123
+ fn check_collapsible_maybe_if_let ( cx : & EarlyContext < ' _ > , then_span : Span , else_ : & ast:: Expr ) {
123
124
if_chain ! {
124
125
if let ast:: ExprKind :: Block ( ref block, _) = else_. kind;
125
126
if !block_starts_with_comment( cx, block) ;
@@ -128,14 +129,23 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) {
128
129
if !else_. span. from_expansion( ) ;
129
130
if let ast:: ExprKind :: If ( ..) = else_. kind;
130
131
then {
132
+ // Prevent "elseif"
133
+ // Check that the "else" is followed by whitespace
134
+ let up_to_else = then_span. between( block. span) ;
135
+ let requires_space = if let Some ( c) = snippet( cx, up_to_else, ".." ) . chars( ) . last( ) { !c. is_whitespace( ) } else { false } ;
136
+
131
137
let mut applicability = Applicability :: MachineApplicable ;
132
138
span_lint_and_sugg(
133
139
cx,
134
140
COLLAPSIBLE_ELSE_IF ,
135
141
block. span,
136
142
"this `else { if .. }` block can be collapsed" ,
137
143
"collapse nested if block" ,
138
- snippet_block_with_applicability( cx, else_. span, ".." , Some ( block. span) , & mut applicability) . into_owned( ) ,
144
+ format!(
145
+ "{}{}" ,
146
+ if requires_space { " " } else { "" } ,
147
+ snippet_block_with_applicability( cx, else_. span, ".." , Some ( block. span) , & mut applicability)
148
+ ) ,
139
149
applicability,
140
150
) ;
141
151
}
0 commit comments