blob: 10ea0c0c3e23e8c1b66787817c3395ce33aaa915 [file] [log] [blame] [edit]
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::SpanRangeExt;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use rustc_span::{Span, sym};
use super::UNNECESSARY_GET_THEN_CHECK;
fn is_a_std_set_type(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
ty.is_diag_item(cx, sym::HashSet) || ty.is_diag_item(cx, sym::BTreeSet)
}
fn is_a_std_map_type(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
ty.is_diag_item(cx, sym::HashMap) || ty.is_diag_item(cx, sym::BTreeMap)
}
pub(super) fn check(
cx: &LateContext<'_>,
call_span: Span,
get_call: &Expr<'_>,
get_caller: &Expr<'_>,
arg: &Expr<'_>,
is_some: bool,
) {
let caller_ty = cx.typeck_results().expr_ty(get_caller);
let is_set = is_a_std_set_type(cx, caller_ty);
let is_map = is_a_std_map_type(cx, caller_ty);
if !is_set && !is_map {
return;
}
let ExprKind::MethodCall(path, _, _, get_call_span) = get_call.kind else {
return;
};
let both_calls_span = get_call_span.with_hi(call_span.hi());
if let Some(snippet) = both_calls_span.get_source_text(cx)
&& let Some(arg_snippet) = arg.span.get_source_text(cx)
{
let generics_snippet = if let Some(generics) = path.args
&& let Some(generics_snippet) = generics.span_ext.get_source_text(cx)
{
format!("::{generics_snippet}")
} else {
String::new()
};
let suggestion = if is_set {
format!("contains{generics_snippet}({arg_snippet})")
} else {
format!("contains_key{generics_snippet}({arg_snippet})")
};
if is_some {
span_lint_and_sugg(
cx,
UNNECESSARY_GET_THEN_CHECK,
both_calls_span,
format!("unnecessary use of `{snippet}`"),
"replace it with",
suggestion,
Applicability::MaybeIncorrect,
);
} else if let Some(caller_snippet) = get_caller.span.get_source_text(cx) {
let full_span = get_caller.span.with_hi(call_span.hi());
span_lint_and_then(
cx,
UNNECESSARY_GET_THEN_CHECK,
both_calls_span,
format!("unnecessary use of `{snippet}`"),
|diag| {
diag.span_suggestion(
full_span,
"replace it with",
format!("{}{caller_snippet}.{suggestion}", if is_some { "" } else { "!" }),
Applicability::MaybeIncorrect,
);
},
);
}
}
}