Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide-assists/src/handlers/generate_delegate_methods.rs63
1 files changed, 55 insertions, 8 deletions
diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index ed1b8f4e28..aecb3826e4 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -1,3 +1,5 @@
+use std::collections::HashSet;
+
use hir::{self, HasCrate, HasSource, HasVisibility};
use syntax::ast::{self, make, AstNode, HasGenericParams, HasName, HasVisibility as _};
@@ -63,16 +65,23 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
};
let sema_field_ty = ctx.sema.resolve_type(&field_ty)?;
- let krate = sema_field_ty.krate(ctx.db());
let mut methods = vec![];
- sema_field_ty.iterate_assoc_items(ctx.db(), krate, |item| {
- if let hir::AssocItem::Function(f) = item {
- if f.self_param(ctx.db()).is_some() && f.is_visible_from(ctx.db(), current_module) {
- methods.push(f)
+ let mut seen_names = HashSet::new();
+
+ for ty in sema_field_ty.autoderef(ctx.db()) {
+ let krate = ty.krate(ctx.db());
+ ty.iterate_assoc_items(ctx.db(), krate, |item| {
+ if let hir::AssocItem::Function(f) = item {
+ if f.self_param(ctx.db()).is_some()
+ && f.is_visible_from(ctx.db(), current_module)
+ && seen_names.insert(f.name(ctx.db()))
+ {
+ methods.push(f)
+ }
}
- }
- Option::<()>::None
- });
+ Option::<()>::None
+ });
+ }
for method in methods {
let adt = ast::Adt::Struct(strukt.clone());
@@ -315,6 +324,44 @@ impl<T> Person<T> {
}
#[test]
+ fn test_generates_delegate_autoderef() {
+ check_assist(
+ generate_delegate_methods,
+ r#"
+//- minicore: deref
+struct Age(u8);
+impl Age {
+ fn age(&self) -> u8 {
+ self.0
+ }
+}
+struct AgeDeref(Age);
+impl core::ops::Deref for AgeDeref { type Target = Age; }
+struct Person {
+ ag$0e: AgeDeref,
+}
+impl Person {}"#,
+ r#"
+struct Age(u8);
+impl Age {
+ fn age(&self) -> u8 {
+ self.0
+ }
+}
+struct AgeDeref(Age);
+impl core::ops::Deref for AgeDeref { type Target = Age; }
+struct Person {
+ age: AgeDeref,
+}
+impl Person {
+ $0fn age(&self) -> u8 {
+ self.age.age()
+ }
+}"#,
+ );
+ }
+
+ #[test]
fn test_generate_delegate_visibility() {
check_assist_not_applicable(
generate_delegate_methods,