11use crate :: utils:: { both, count_eq, eq_expr_value, in_macro, search_same, SpanlessEq , SpanlessHash } ;
22use crate :: utils:: {
3- first_line_of_span, get_parent_expr, higher, if_sequence, indent_of, reindent_multiline , snippet ,
4- span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
3+ first_line_of_span, get_parent_expr, higher, if_sequence, indent_of, parent_node_is_if_expr , reindent_multiline ,
4+ snippet , span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
55} ;
66use rustc_data_structures:: fx:: FxHashSet ;
77use rustc_errors:: Applicability ;
@@ -141,7 +141,7 @@ declare_clippy_lint! {
141141 /// };
142142 /// ```
143143 pub SHARED_CODE_IN_IF_BLOCKS ,
144- pedantic ,
144+ nursery ,
145145 "`if` statement with shared code in all blocks"
146146}
147147
@@ -185,7 +185,7 @@ fn lint_same_then_else<'tcx>(
185185) {
186186 // We only lint ifs with multiple blocks
187187 // TODO xFrednet 2021-01-01: Check if it's an else if block
188- if blocks. len ( ) < 2 {
188+ if blocks. len ( ) < 2 || parent_node_is_if_expr ( expr , cx ) {
189189 return ;
190190 }
191191
@@ -195,7 +195,7 @@ fn lint_same_then_else<'tcx>(
195195 let mut start_eq = usize:: MAX ;
196196 let mut end_eq = usize:: MAX ;
197197 let mut expr_eq = true ;
198- for ( index , win) in blocks. windows ( 2 ) . enumerate ( ) {
198+ for win in blocks. windows ( 2 ) {
199199 let l_stmts = win[ 0 ] . stmts ;
200200 let r_stmts = win[ 1 ] . stmts ;
201201
@@ -207,9 +207,7 @@ fn lint_same_then_else<'tcx>(
207207 let block_expr_eq = both ( & win[ 0 ] . expr , & win[ 1 ] . expr , |l, r| evaluator. eq_expr ( l, r) ) ;
208208
209209 // IF_SAME_THEN_ELSE
210- // We only lint the first two blocks (index == 0). Further blocks will be linted when that if
211- // statement is checked
212- if index == 0 && block_expr_eq && l_stmts. len ( ) == r_stmts. len ( ) && l_stmts. len ( ) == current_start_eq {
210+ if block_expr_eq && l_stmts. len ( ) == r_stmts. len ( ) && l_stmts. len ( ) == current_start_eq {
213211 span_lint_and_note (
214212 cx,
215213 IF_SAME_THEN_ELSE ,
@@ -220,16 +218,24 @@ fn lint_same_then_else<'tcx>(
220218 ) ;
221219
222220 return ;
221+ } else {
222+ println ! (
223+ "{:?}\n - expr_eq: {:10}, l_stmts.len(): {:10}, r_stmts.len(): {:10}" ,
224+ win[ 0 ] . span,
225+ block_expr_eq,
226+ l_stmts. len( ) ,
227+ r_stmts. len( )
228+ )
223229 }
224230
225231 start_eq = start_eq. min ( current_start_eq) ;
226232 end_eq = end_eq. min ( current_end_eq) ;
227233 expr_eq &= block_expr_eq;
234+ }
228235
229- // We can return if the eq count is 0 from both sides or if it has no unconditional else case
230- if !has_unconditional_else || ( start_eq == 0 && end_eq == 0 && ( has_expr && !expr_eq) ) {
231- return ;
232- }
236+ // SHARED_CODE_IN_IF_BLOCKS prerequisites
237+ if !has_unconditional_else || ( start_eq == 0 && end_eq == 0 && ( has_expr && !expr_eq) ) {
238+ return ;
233239 }
234240
235241 if has_expr && !expr_eq {
@@ -280,11 +286,14 @@ fn lint_same_then_else<'tcx>(
280286 end_eq -= moved_start;
281287 }
282288
283- let mut end_linable = true ;
284- if let Some ( expr) = block. expr {
289+ let end_linable = if let Some ( expr) = block. expr {
285290 intravisit:: walk_expr ( & mut walker, expr) ;
286- end_linable = walker. uses . iter ( ) . any ( |x| !block_defs. contains ( x) ) ;
287- }
291+ walker. uses . iter ( ) . any ( |x| !block_defs. contains ( x) )
292+ } else if end_eq == 0 {
293+ false
294+ } else {
295+ true
296+ } ;
288297
289298 emit_shared_code_in_if_blocks_lint ( cx, start_eq, end_eq, end_linable, blocks, expr) ;
290299 }
@@ -356,7 +365,7 @@ fn emit_shared_code_in_if_blocks_lint(
356365 SHARED_CODE_IN_IF_BLOCKS ,
357366 * span,
358367 "All code blocks contain the same code" ,
359- "Consider moving the code out like this" ,
368+ "Consider moving the statements out like this" ,
360369 sugg. clone ( ) ,
361370 Applicability :: Unspecified ,
362371 ) ;
0 commit comments