3 use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
4 use rustc::lint::LateContext;
6 use syntax::codemap::Span;
7 use crate::utils::{get_pat_name, match_var, snippet};
11 opt_body_id: Option<BodyId>,
13 replacements: &'static [(&'static str, &'static str)],
14 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
15 if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) {
16 get_binding_name(&body.arguments[idx])
17 .map_or_else(|| Some(vec![]), |name| extract_clone_suggestions(cx, name, replacements, body))
23 fn extract_clone_suggestions<'a, 'tcx: 'a>(
24 cx: &LateContext<'a, 'tcx>,
26 replace: &'static [(&'static str, &'static str)],
28 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
29 let mut visitor = PtrCloneVisitor {
36 visitor.visit_body(body);
44 struct PtrCloneVisitor<'a, 'tcx: 'a> {
45 cx: &'a LateContext<'a, 'tcx>,
47 replace: &'static [(&'static str, &'static str)],
48 spans: Vec<(Span, Cow<'static, str>)>,
52 impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
53 fn visit_expr(&mut self, expr: &'tcx Expr) {
57 if let ExprKind::MethodCall(ref seg, _, ref args) = expr.node {
58 if args.len() == 1 && match_var(&args[0], self.name) {
59 if seg.ident.name == "capacity" {
63 for &(fn_name, suffix) in self.replace {
64 if seg.ident.name == fn_name {
66 .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix));
73 walk_expr(self, expr);
76 fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
77 NestedVisitorMap::None
81 fn get_binding_name(arg: &Arg) -> Option<Name> {
82 get_pat_name(&arg.pat)