Auto merge of #14483 - jhgg:fix/generate-delegate-methods-autoderef, r=Veykril

assist: autoderef in generate delegate methods

fixes #14438
This commit is contained in:
bors 2023-04-04 09:35:56 +00:00
commit a6464392c1

View File

@ -1,3 +1,5 @@
use std::collections::HashSet;
use hir::{self, HasCrate, HasSource, HasVisibility}; use hir::{self, HasCrate, HasSource, HasVisibility};
use syntax::ast::{self, make, AstNode, HasGenericParams, HasName, HasVisibility as _}; 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 sema_field_ty = ctx.sema.resolve_type(&field_ty)?;
let krate = sema_field_ty.krate(ctx.db());
let mut methods = vec![]; let mut methods = vec![];
sema_field_ty.iterate_assoc_items(ctx.db(), krate, |item| { let mut seen_names = HashSet::new();
if let hir::AssocItem::Function(f) = item {
if f.self_param(ctx.db()).is_some() && f.is_visible_from(ctx.db(), current_module) { for ty in sema_field_ty.autoderef(ctx.db()) {
methods.push(f) 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 { for method in methods {
let adt = ast::Adt::Struct(strukt.clone()); let adt = ast::Adt::Struct(strukt.clone());
@ -314,6 +323,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] #[test]
fn test_generate_delegate_visibility() { fn test_generate_delegate_visibility() {
check_assist_not_applicable( check_assist_not_applicable(