]>
Commit | Line | Data |
---|---|---|
487cf647 FG |
1 | use rustc_ast::ast::{LitIntType, LitKind}; |
2 | use rustc_errors::Applicability; | |
3 | use rustc_hir::{Expr, ExprKind}; | |
4 | use rustc_lint::LateContext; | |
5 | ||
add651ee FG |
6 | use clippy_utils::diagnostics::span_lint_and_sugg; |
7 | use clippy_utils::source::snippet_with_applicability; | |
8 | use clippy_utils::ty::implements_trait; | |
9 | use clippy_utils::{get_trait_def_id, match_def_path, paths}; | |
487cf647 FG |
10 | |
11 | use super::SEEK_FROM_CURRENT; | |
12 | ||
13 | pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { | |
14 | let ty = cx.typeck_results().expr_ty(recv); | |
15 | ||
16 | if let Some(def_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) { | |
17 | if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) { | |
18 | let mut applicability = Applicability::MachineApplicable; | |
19 | let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability); | |
20 | ||
21 | span_lint_and_sugg( | |
22 | cx, | |
23 | SEEK_FROM_CURRENT, | |
24 | expr.span, | |
25 | "using `SeekFrom::Current` to start from current position", | |
26 | "replace with", | |
27 | format!("{snip}.stream_position()"), | |
28 | applicability, | |
29 | ); | |
30 | } | |
31 | } | |
32 | } | |
33 | ||
34 | fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { | |
35 | if let ExprKind::Call(f, args) = expr.kind && | |
36 | let ExprKind::Path(ref path) = f.kind && | |
37 | let Some(def_id) = cx.qpath_res(path, f.hir_id).opt_def_id() && | |
38 | match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT) { | |
39 | // check if argument of `SeekFrom::Current` is `0` | |
40 | if args.len() == 1 && | |
49aad941 | 41 | let ExprKind::Lit(lit) = args[0].kind && |
487cf647 FG |
42 | let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node { |
43 | return true | |
44 | } | |
45 | } | |
46 | ||
47 | false | |
48 | } |