<commit_before>use crate::utils::{
    contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
    span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::{Name, UintTy};

declare_clippy_lint! {
    /// **What it does:** Checks for naive byte counts
    ///
    /// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount)
    /// crate has methods to count your bytes faster, especially for large slices.
    ///
    /// **Known problems:** If you have predominantly small slices, the
    /// `bytecount::count(..)` method may actually be slower. However, if you can
    /// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
    /// faster in those cases.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
    /// ```
    pub NAIVE_BYTECOUNT,
    perf,
    "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
}

declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
            if count.ident.name == "count";
            if count_args.len() == 1;
            if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
            if filter.ident.name == "filter";
            if filter_args.len() == 2;
            if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
            then {
                let body = cx.tcx.hir().body(body_id);
                if_chain! {
                    if body.arguments.len() == 1;
                    if let Some(argname) = get_pat_name(&body.arguments[0].pat);
                    if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node;
                    if op.node == BinOpKind::Eq;
                    if match_type(cx,
                               walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
                               &paths::SLICE_ITER);
                    then {
                        let needle = match get_path_name(l) {
                            Some(name) if check_arg(name, argname, r) => r,
                            _ => match get_path_name(r) {
                                Some(name) if check_arg(name, argname, l) => l,
                                _ => { return; }
                            }
                        };
                        if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
                            return;
                        }
                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
                                filter_args[0].node {
                            let p = path.ident.name;
                            if (p == "iter" || p == "iter_mut") && args.len() == 1 {
                                &args[0]
                            } else {
                                &filter_args[0]
                            }
                        } else {
                            &filter_args[0]
                        };
                        let mut applicability = Applicability::MachineApplicable;
                        span_lint_and_sugg(
                            cx,
                            NAIVE_BYTECOUNT,<commit_msg>Auto merge of #3984 - phansch:bytecount_sugg, r=flip1995<commit_after>use crate::utils::{
    contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
    span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::{Name, UintTy};

declare_clippy_lint! {
    /// **What it does:** Checks for naive byte counts
    ///
    /// **Why is this bad?** The [`bytecount`](https://crates.io/crates/bytecount)
    /// crate has methods to count your bytes faster, especially for large slices.
    ///
    /// **Known problems:** If you have predominantly small slices, the
    /// `bytecount::count(..)` method may actually be slower. However, if you can
    /// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
    /// faster in those cases.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
    /// ```
    pub NAIVE_BYTECOUNT,
    perf,
    "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
}

declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
            if count.ident.name == "count";
            if count_args.len() == 1;
            if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
            if filter.ident.name == "filter";
            if filter_args.len() == 2;
            if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
            then {
                let body = cx.tcx.hir().body(body_id);
                if_chain! {
                    if body.arguments.len() == 1;
                    if let Some(argname) = get_pat_name(&body.arguments[0].pat);
                    if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node;
                    if op.node == BinOpKind::Eq;
                    if match_type(cx,
                               walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
                               &paths::SLICE_ITER);
                    then {
                        let needle = match get_path_name(l) {
                            Some(name) if check_arg(name, argname, r) => r,
                            _ => match get_path_name(r) {
                                Some(name) if check_arg(name, argname, l) => l,
                                _ => { return; }
                            }
                        };
                        if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
                            return;
                        }
                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
                                filter_args[0].node {
                            let p = path.ident.name;
                            if (p == "iter" || p == "iter_mut") && args.len() == 1 {
                                &args[0]
                            } else {
                                &filter_args[0]
                            }
                        } else {
                            &filter_args[0]
                        };
                        let mut applicability = Applicability::MaybeIncorrect;
                        span_lint_and_sugg(
                            cx,
                            NAIVE_BYTECOUNT,
{'fraction_non_alphanumeric': 0.1274905761981691, 'fraction_numerical': 0.006192784060312331, 'mean_word_length': 1.4664674634794157, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6692517', 'n_tokens_mistral': 2194, 'n_tokens_neox': 2131, 'n_words': 486}