1 use crate::utils::{get_pat_name, match_var, snippet};
2 use rustc::hir::map::Map;
3 use rustc_ast::ast::Name;
4 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
5 use rustc_hir::{Body, BodyId, Expr, ExprKind, Param};
6 use rustc_lint::LateContext;
7 use rustc_span::source_map::Span;
11 cx: &LateContext<'_, '_>,
12 opt_body_id: Option<BodyId>,
14 replacements: &[(&'static str, &'static str)],
15 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
16 if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
17 get_binding_name(&body.params[idx]).map_or_else(
19 |name| extract_clone_suggestions(cx, name, replacements, body),
26 fn extract_clone_suggestions<'a, 'tcx>(
27 cx: &LateContext<'a, 'tcx>,
29 replace: &[(&'static str, &'static str)],
31 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
32 let mut visitor = PtrCloneVisitor {
39 visitor.visit_body(body);
47 struct PtrCloneVisitor<'a, 'tcx> {
48 cx: &'a LateContext<'a, 'tcx>,
50 replace: &'a [(&'static str, &'static str)],
51 spans: Vec<(Span, Cow<'static, str>)>,
55 impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
58 fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
62 if let ExprKind::MethodCall(ref seg, _, ref args) = expr.kind {
63 if args.len() == 1 && match_var(&args[0], self.name) {
64 if seg.ident.name.as_str() == "capacity" {
68 for &(fn_name, suffix) in self.replace {
69 if seg.ident.name.as_str() == fn_name {
71 .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix));
78 walk_expr(self, expr);
81 fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
82 NestedVisitorMap::None
86 fn get_binding_name(arg: &Param<'_>) -> Option<Name> {
87 get_pat_name(&arg.pat)