59 lines
1.8 KiB
Rust
59 lines
1.8 KiB
Rust
use clippy_utils::diagnostics::span_lint_and_sugg;
|
|
use clippy_utils::{is_trait_method, match_qpath, paths};
|
|
use if_chain::if_chain;
|
|
use rustc_errors::Applicability;
|
|
use rustc_hir as hir;
|
|
use rustc_lint::LateContext;
|
|
use rustc_span::{source_map::Span, sym};
|
|
|
|
use super::FLAT_MAP_IDENTITY;
|
|
|
|
/// lint use of `flat_map` for `Iterators` where `flatten` would be sufficient
|
|
pub(super) fn check<'tcx>(
|
|
cx: &LateContext<'tcx>,
|
|
expr: &'tcx hir::Expr<'_>,
|
|
flat_map_arg: &'tcx hir::Expr<'_>,
|
|
flat_map_span: Span,
|
|
) {
|
|
if is_trait_method(cx, expr, sym::Iterator) {
|
|
let arg_node = &flat_map_arg.kind;
|
|
|
|
let apply_lint = |message: &str| {
|
|
span_lint_and_sugg(
|
|
cx,
|
|
FLAT_MAP_IDENTITY,
|
|
flat_map_span.with_hi(expr.span.hi()),
|
|
message,
|
|
"try",
|
|
"flatten()".to_string(),
|
|
Applicability::MachineApplicable,
|
|
);
|
|
};
|
|
|
|
if_chain! {
|
|
if let hir::ExprKind::Closure(_, _, body_id, _, _) = arg_node;
|
|
let body = cx.tcx.hir().body(*body_id);
|
|
|
|
if let hir::PatKind::Binding(_, _, binding_ident, _) = body.params[0].pat.kind;
|
|
if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = body.value.kind;
|
|
|
|
if path.segments.len() == 1;
|
|
if path.segments[0].ident.name == binding_ident.name;
|
|
|
|
then {
|
|
apply_lint("called `flat_map(|x| x)` on an `Iterator`");
|
|
}
|
|
}
|
|
|
|
if_chain! {
|
|
if let hir::ExprKind::Path(ref qpath) = arg_node;
|
|
|
|
if match_qpath(qpath, &paths::STD_CONVERT_IDENTITY);
|
|
|
|
then {
|
|
apply_lint("called `flat_map(std::convert::identity)` on an `Iterator`");
|
|
}
|
|
}
|
|
}
|
|
}
|