|
| 1 | +use std::collections::HashSet; |
| 2 | + |
1 | 3 | use hir::{self, HasCrate, HasSource, HasVisibility};
|
2 | 4 | use syntax::ast::{self, make, AstNode, HasGenericParams, HasName, HasVisibility as _};
|
3 | 5 |
|
@@ -63,16 +65,23 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
63 | 65 | };
|
64 | 66 |
|
65 | 67 | let sema_field_ty = ctx.sema.resolve_type(&field_ty)?;
|
66 |
| - let krate = sema_field_ty.krate(ctx.db()); |
67 | 68 | let mut methods = vec![];
|
68 |
| - sema_field_ty.iterate_assoc_items(ctx.db(), krate, |item| { |
69 |
| - if let hir::AssocItem::Function(f) = item { |
70 |
| - if f.self_param(ctx.db()).is_some() && f.is_visible_from(ctx.db(), current_module) { |
71 |
| - methods.push(f) |
| 69 | + let mut seen_names = HashSet::new(); |
| 70 | + |
| 71 | + for ty in sema_field_ty.autoderef(ctx.db()) { |
| 72 | + let krate = ty.krate(ctx.db()); |
| 73 | + ty.iterate_assoc_items(ctx.db(), krate, |item| { |
| 74 | + if let hir::AssocItem::Function(f) = item { |
| 75 | + if f.self_param(ctx.db()).is_some() |
| 76 | + && f.is_visible_from(ctx.db(), current_module) |
| 77 | + && seen_names.insert(f.name(ctx.db())) |
| 78 | + { |
| 79 | + methods.push(f) |
| 80 | + } |
72 | 81 | }
|
73 |
| - } |
74 |
| - Option::<()>::None |
75 |
| - }); |
| 82 | + Option::<()>::None |
| 83 | + }); |
| 84 | + } |
76 | 85 |
|
77 | 86 | for method in methods {
|
78 | 87 | let adt = ast::Adt::Struct(strukt.clone());
|
@@ -314,6 +323,44 @@ impl<T> Person<T> {
|
314 | 323 | );
|
315 | 324 | }
|
316 | 325 |
|
| 326 | + #[test] |
| 327 | + fn test_generates_delegate_autoderef() { |
| 328 | + check_assist( |
| 329 | + generate_delegate_methods, |
| 330 | + r#" |
| 331 | +//- minicore: deref |
| 332 | +struct Age(u8); |
| 333 | +impl Age { |
| 334 | + fn age(&self) -> u8 { |
| 335 | + self.0 |
| 336 | + } |
| 337 | +} |
| 338 | +struct AgeDeref(Age); |
| 339 | +impl core::ops::Deref for AgeDeref { type Target = Age; } |
| 340 | +struct Person { |
| 341 | + ag$0e: AgeDeref, |
| 342 | +} |
| 343 | +impl Person {}"#, |
| 344 | + r#" |
| 345 | +struct Age(u8); |
| 346 | +impl Age { |
| 347 | + fn age(&self) -> u8 { |
| 348 | + self.0 |
| 349 | + } |
| 350 | +} |
| 351 | +struct AgeDeref(Age); |
| 352 | +impl core::ops::Deref for AgeDeref { type Target = Age; } |
| 353 | +struct Person { |
| 354 | + age: AgeDeref, |
| 355 | +} |
| 356 | +impl Person { |
| 357 | + $0fn age(&self) -> u8 { |
| 358 | + self.age.age() |
| 359 | + } |
| 360 | +}"#, |
| 361 | + ); |
| 362 | + } |
| 363 | + |
317 | 364 | #[test]
|
318 | 365 | fn test_generate_delegate_visibility() {
|
319 | 366 | check_assist_not_applicable(
|
|
0 commit comments