From 94e6a6642c0c4aacc3cc30163c0a7d3d27386ae8 Mon Sep 17 00:00:00 2001 From: Jake Heinz Date: Tue, 4 Apr 2023 06:50:20 +0000 Subject: [PATCH 1/3] assist: autoderef in generate delegate methods --- .../src/handlers/generate_delegate_methods.rs | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index ed1b8f4e28d..483ed165a55 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -65,14 +65,17 @@ 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) + + for ty in sema_field_ty.autoderef(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) { + methods.push(f) + } } - } - Option::<()>::None - }); + Option::<()>::None + }); + } for method in methods { let adt = ast::Adt::Struct(strukt.clone()); @@ -314,6 +317,44 @@ impl Person { ); } + #[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( From 50b427c0d14aa20a4fb2e5422655bb8b790b4133 Mon Sep 17 00:00:00 2001 From: Jake Heinz Date: Tue, 4 Apr 2023 06:54:26 +0000 Subject: [PATCH 2/3] use crate from autoderef ty --- crates/ide-assists/src/handlers/generate_delegate_methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 483ed165a55..fde75e8d7df 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -63,10 +63,10 @@ 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![]; 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) { From f6b0c19c56e4e046fa3dfb29f22bfd49b98ca338 Mon Sep 17 00:00:00 2001 From: Jake Heinz Date: Tue, 4 Apr 2023 06:57:02 +0000 Subject: [PATCH 3/3] dedupe by name --- .../ide-assists/src/handlers/generate_delegate_methods.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index fde75e8d7df..aecb3826e47 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 _}; @@ -64,12 +66,16 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let sema_field_ty = ctx.sema.resolve_type(&field_ty)?; let mut methods = vec![]; + 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) { + 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) } }