]> git.lizzy.rs Git - rust.git/blobdiff - clippy_utils/src/ptr.rs
separate the receiver from arguments in HIR under /clippy
[rust.git] / clippy_utils / src / ptr.rs
index 791688cd194a997a75461edc103998525e434df4..0226f74906b5152b66a678c960200fcd844564da 100644 (file)
@@ -1,10 +1,10 @@
 use crate::source::snippet;
-use crate::{get_pat_name, match_var};
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
-use rustc_hir::{Body, BodyId, Expr, ExprKind, Param};
+use crate::visitors::expr_visitor_no_bodies;
+use crate::{path_to_local_id, strip_pat_refs};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind};
 use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 use std::borrow::Cow;
 
 pub fn get_spans(
@@ -14,10 +14,11 @@ pub fn get_spans(
     replacements: &[(&'static str, &'static str)],
 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
     if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
-        get_binding_name(&body.params[idx]).map_or_else(
-            || Some(vec![]),
-            |name| extract_clone_suggestions(cx, name, replacements, body),
-        )
+        if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind {
+            extract_clone_suggestions(cx, binding_id, replacements, body)
+        } else {
+            Some(vec![])
+        }
     } else {
         Some(vec![])
     }
@@ -25,59 +26,32 @@ pub fn get_spans(
 
 fn extract_clone_suggestions<'tcx>(
     cx: &LateContext<'tcx>,
-    name: Symbol,
+    id: HirId,
     replace: &[(&'static str, &'static str)],
     body: &'tcx Body<'_>,
 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
-    let mut visitor = PtrCloneVisitor {
-        cx,
-        name,
-        replace,
-        spans: vec![],
-        abort: false,
-    };
-    visitor.visit_body(body);
-    if visitor.abort { None } else { Some(visitor.spans) }
-}
-
-struct PtrCloneVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    name: Symbol,
-    replace: &'a [(&'static str, &'static str)],
-    spans: Vec<(Span, Cow<'static, str>)>,
-    abort: bool,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.abort {
-            return;
+    let mut abort = false;
+    let mut spans = Vec::new();
+    expr_visitor_no_bodies(|expr| {
+        if abort {
+            return false;
         }
-        if let ExprKind::MethodCall(seg, _, args, _) = expr.kind {
-            if args.len() == 1 && match_var(&args[0], self.name) {
+        if let ExprKind::MethodCall(seg, recv, [], _) = expr.kind {
+            if path_to_local_id(recv, id) {
                 if seg.ident.name.as_str() == "capacity" {
-                    self.abort = true;
-                    return;
+                    abort = true;
+                    return false;
                 }
-                for &(fn_name, suffix) in self.replace {
+                for &(fn_name, suffix) in replace {
                     if seg.ident.name.as_str() == fn_name {
-                        self.spans
-                            .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix));
-                        return;
+                        spans.push((expr.span, snippet(cx, recv.span, "_") + suffix));
+                        return false;
                     }
                 }
             }
         }
-        walk_expr(self, expr);
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-}
-
-fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> {
-    get_pat_name(arg.pat)
+        !abort
+    })
+    .visit_body(body);
+    if abort { None } else { Some(spans) }
 }