]>
Commit | Line | Data |
---|---|---|
17df50a5 XL |
1 | use clippy_utils::diagnostics::span_lint_and_note; |
2 | use if_chain::if_chain; | |
3 | use rustc_ast::LitKind; | |
4 | use rustc_hir::{Expr, ExprKind}; | |
5 | use rustc_lint::LateContext; | |
6 | use rustc_span::source_map::Spanned; | |
7 | ||
8 | use super::SUSPICIOUS_SPLITN; | |
9 | ||
c295e0f8 | 10 | pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) { |
17df50a5 | 11 | if_chain! { |
17df50a5 XL |
12 | if count <= 1; |
13 | if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); | |
14 | if let Some(impl_id) = cx.tcx.impl_of_method(call_id); | |
ee023bcb FG |
15 | if cx.tcx.impl_trait_ref(impl_id).is_none(); |
16 | let self_ty = cx.tcx.type_of(impl_id); | |
17 | if self_ty.is_slice() || self_ty.is_str(); | |
17df50a5 XL |
18 | then { |
19 | // Ignore empty slice and string literals when used with a literal count. | |
c295e0f8 | 20 | if matches!(self_arg.kind, ExprKind::Array([])) |
17df50a5 | 21 | || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) |
17df50a5 XL |
22 | { |
23 | return; | |
24 | } | |
25 | ||
26 | let (msg, note_msg) = if count == 0 { | |
27 | (format!("`{}` called with `0` splits", method_name), | |
28 | "the resulting iterator will always return `None`") | |
29 | } else { | |
30 | (format!("`{}` called with `1` split", method_name), | |
ee023bcb | 31 | if self_ty.is_slice() { |
17df50a5 XL |
32 | "the resulting iterator will always return the entire slice followed by `None`" |
33 | } else { | |
34 | "the resulting iterator will always return the entire string followed by `None`" | |
35 | }) | |
36 | }; | |
37 | ||
38 | span_lint_and_note( | |
39 | cx, | |
40 | SUSPICIOUS_SPLITN, | |
41 | expr.span, | |
42 | &msg, | |
43 | None, | |
44 | note_msg, | |
45 | ); | |
46 | } | |
47 | } | |
48 | } |