Skip to content

Commit

Permalink
Refactor check_for_single_element_loop to its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
nahuakang authored and Y-Nak committed Mar 2, 2021
1 parent 71026ca commit 1e5e541
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 39 deletions.
42 changes: 42 additions & 0 deletions clippy_lints/src/loops/for_single_element_loop.rs
@@ -0,0 +1,42 @@
use super::get_span_of_entire_for_loop;
use crate::utils::{indent_of, single_segment_path, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind};
use rustc_lint::LateContext;

pub(super) fn check_for_single_element_loop<'tcx>(
cx: &LateContext<'tcx>,
pat: &'tcx Pat<'_>,
arg: &'tcx Expr<'_>,
body: &'tcx Expr<'_>,
expr: &'tcx Expr<'_>,
) {
if_chain! {
if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind;
if let PatKind::Binding(.., target, _) = pat.kind;
if let ExprKind::Array([arg_expression]) = arg_expr.kind;
if let ExprKind::Path(ref list_item) = arg_expression.kind;
if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
if let ExprKind::Block(ref block, _) = body.kind;
if !block.stmts.is_empty();

then {
let for_span = get_span_of_entire_for_loop(expr);
let mut block_str = snippet(cx, block.span, "..").into_owned();
block_str.remove(0);
block_str.pop();


span_lint_and_sugg(
cx,
super::SINGLE_ELEMENT_LOOP,
for_span,
"for loop over a single element",
"try",
format!("{{\n{}let {} = &{};{}}}", " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)), target.name, list_item_name, block_str),
Applicability::MachineApplicable
)
}
}
}
43 changes: 4 additions & 39 deletions clippy_lints/src/loops/mod.rs
Expand Up @@ -3,16 +3,17 @@ mod for_loop_explicit_counter;
mod for_loop_over_map_kv;
mod for_loop_range;
mod for_mut_range_bound;
mod for_single_element_loop;
mod manual_flatten;
mod utils;

use crate::consts::constant;
use crate::utils::sugg::Sugg;
use crate::utils::usage::mutated_variables;
use crate::utils::{
get_enclosing_block, get_parent_expr, get_trait_def_id, higher, implements_trait, indent_of, is_in_panic_handler,
get_enclosing_block, get_parent_expr, get_trait_def_id, higher, implements_trait, is_in_panic_handler,
is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item, last_path_segment, match_trait_method,
match_type, path_to_local, path_to_local_id, paths, single_segment_path, snippet, snippet_with_applicability,
match_type, path_to_local, path_to_local_id, paths, snippet, snippet_with_applicability,
snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg,
};
use if_chain::if_chain;
Expand Down Expand Up @@ -863,7 +864,7 @@ fn check_for_loop<'tcx>(
for_loop_arg::check_for_loop_arg(cx, pat, arg, expr);
for_loop_over_map_kv::check_for_loop_over_map_kv(cx, pat, arg, body, expr);
for_mut_range_bound::check_for_mut_range_bound(cx, arg, body);
check_for_single_element_loop(cx, pat, arg, body, expr);
for_single_element_loop::check_for_single_element_loop(cx, pat, arg, body, expr);
detect_same_item_push(cx, pat, arg, body, expr);
manual_flatten::check_manual_flatten(cx, pat, arg, body, span);
}
Expand Down Expand Up @@ -1464,42 +1465,6 @@ fn detect_same_item_push<'tcx>(
}
}

fn check_for_single_element_loop<'tcx>(
cx: &LateContext<'tcx>,
pat: &'tcx Pat<'_>,
arg: &'tcx Expr<'_>,
body: &'tcx Expr<'_>,
expr: &'tcx Expr<'_>,
) {
if_chain! {
if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind;
if let PatKind::Binding(.., target, _) = pat.kind;
if let ExprKind::Array([arg_expression]) = arg_expr.kind;
if let ExprKind::Path(ref list_item) = arg_expression.kind;
if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
if let ExprKind::Block(ref block, _) = body.kind;
if !block.stmts.is_empty();

then {
let for_span = get_span_of_entire_for_loop(expr);
let mut block_str = snippet(cx, block.span, "..").into_owned();
block_str.remove(0);
block_str.pop();


span_lint_and_sugg(
cx,
SINGLE_ELEMENT_LOOP,
for_span,
"for loop over a single element",
"try",
format!("{{\n{}let {} = &{};{}}}", " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)), target.name, list_item_name, block_str),
Applicability::MachineApplicable
)
}
}
}

fn is_used_inside<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, container: &'tcx Expr<'_>) -> bool {
let def_id = match path_to_local(expr) {
Some(id) => id,
Expand Down

0 comments on commit 1e5e541

Please sign in to comment.