]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/completions/dot.rs
Merge #11393
[rust.git] / crates / ide_completion / src / completions / dot.rs
index e7371270fbf6d5ad9be3a51e72f67282cc9a8603..b8bab941706f8e4480da65b3316359c90ed3df4e 100644 (file)
@@ -1,7 +1,6 @@
 //! Completes references after dot (fields and method calls).
 
 use either::Either;
-use hir::ScopeDef;
 use rustc_hash::FxHashSet;
 
 use crate::{context::CompletionContext, patterns::ImmediateLocation, Completions};
@@ -36,24 +35,22 @@ fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
     if !ctx.is_trivial_path() || ctx.is_path_disallowed() || !ctx.expects_expression() {
         return;
     }
-    ctx.scope.process_all_names(&mut |name, def| {
-        if let ScopeDef::Local(local) = &def {
-            if local.is_self(ctx.db) {
-                let ty = local.ty(ctx.db);
-                complete_fields(ctx, &ty, |field, ty| match field {
-                    either::Either::Left(field) => {
-                        acc.add_field(ctx, Some(name.clone()), field, &ty)
-                    }
-                    either::Either::Right(tuple_idx) => {
-                        acc.add_tuple_field(ctx, Some(name.clone()), tuple_idx, &ty)
-                    }
-                });
-                complete_methods(ctx, &ty, |func| {
-                    acc.add_method(ctx, func, Some(name.clone()), None)
-                });
-            }
+    if let Some(func) = ctx.function_def.as_ref().and_then(|fn_| ctx.sema.to_def(fn_)) {
+        if let Some(self_) = func.self_param(ctx.db) {
+            let ty = self_.ty(ctx.db);
+            complete_fields(ctx, &ty, |field, ty| match field {
+                either::Either::Left(field) => {
+                    acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty)
+                }
+                either::Either::Right(tuple_idx) => {
+                    acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), tuple_idx, &ty)
+                }
+            });
+            complete_methods(ctx, &ty, |func| {
+                acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
+            });
         }
-    });
+    }
 }
 
 fn complete_fields(
@@ -79,13 +76,27 @@ fn complete_methods(
 ) {
     if let Some(krate) = ctx.krate {
         let mut seen_methods = FxHashSet::default();
-        let traits_in_scope = ctx.scope.visible_traits();
-        receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
-            if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
-                f(func);
-            }
-            None::<()>
-        });
+        let mut traits_in_scope = ctx.scope.visible_traits();
+
+        // Remove drop from the environment as calling `Drop::drop` is not allowed
+        if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
+            cov_mark::hit!(dot_remove_drop_trait);
+            traits_in_scope.remove(&drop_trait.into());
+        }
+
+        receiver.iterate_method_candidates(
+            ctx.db,
+            krate,
+            &traits_in_scope,
+            ctx.module,
+            None,
+            |_ty, func| {
+                if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
+                    f(func);
+                }
+                None::<()>
+            },
+        );
     }
 }
 
@@ -261,6 +272,37 @@ fn foo(a: lib::A) { a.$0 }
         );
     }
 
+    #[test]
+    fn test_local_impls() {
+        check(
+            r#"
+//- /lib.rs crate:lib
+pub struct A {}
+mod m {
+    impl super::A {
+        pub fn pub_module_method(&self) {}
+    }
+    fn f() {
+        impl super::A {
+            pub fn pub_foreign_local_method(&self) {}
+        }
+    }
+}
+//- /main.rs crate:main deps:lib
+fn foo(a: lib::A) {
+    impl lib::A {
+        fn local_method(&self) {}
+    }
+    a.$0
+}
+"#,
+            expect![[r#"
+                me local_method()      fn(&self)
+                me pub_module_method() fn(&self)
+            "#]],
+        );
+    }
+
     #[test]
     fn test_doc_hidden_filtering() {
         check(
@@ -712,4 +754,34 @@ fn main() {
             "#]],
         )
     }
+
+    #[test]
+    fn postfix_drop_completion() {
+        cov_mark::check!(dot_remove_drop_trait);
+        cov_mark::check!(postfix_drop_completion);
+        check_edit(
+            "drop",
+            r#"
+//- minicore: drop
+struct Vec<T>(T);
+impl<T> Drop for Vec<T> {
+    fn drop(&mut self) {}
+}
+fn main() {
+    let x = Vec(0u32)
+    x.$0;
+}
+"#,
+            r"
+struct Vec<T>(T);
+impl<T> Drop for Vec<T> {
+    fn drop(&mut self) {}
+}
+fn main() {
+    let x = Vec(0u32)
+    drop($0x);
+}
+",
+        )
+    }
 }