Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/completions/item_list/trait_impl.rs')
| -rw-r--r-- | crates/ide-completion/src/completions/item_list/trait_impl.rs | 108 |
1 files changed, 106 insertions, 2 deletions
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs index 7de1bf2dc1..269e40e6ef 100644 --- a/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -227,9 +227,8 @@ fn get_transformed_assoc_item( assoc_item: ast::AssocItem, impl_def: hir::Impl, ) -> Option<ast::AssocItem> { - let assoc_item = assoc_item.clone_for_update(); let trait_ = impl_def.trait_(ctx.db)?; - let source_scope = &ctx.sema.scope_for_def(trait_); + let source_scope = &ctx.sema.scope(assoc_item.syntax())?; let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?; let transform = PathTransform::trait_impl( target_scope, @@ -238,6 +237,9 @@ fn get_transformed_assoc_item( ctx.sema.source(impl_def)?.value, ); + let assoc_item = assoc_item.clone_for_update(); + // FIXME: Paths in nested macros are not handled well. See + // `macro_generated_assoc_item2` test. transform.apply(assoc_item.syntax()); assoc_item.remove_attrs_and_docs(); Some(assoc_item) @@ -834,6 +836,33 @@ impl Test for () { } #[test] + fn fn_with_lifetimes() { + check_edit( + "fn foo", + r#" +trait Test<'a, 'b, T> { + fn foo(&self, a: &'a T, b: &'b T) -> &'a T; +} + +impl<'x, 'y, A> Test<'x, 'y, A> for () { + t$0 +} +"#, + r#" +trait Test<'a, 'b, T> { + fn foo(&self, a: &'a T, b: &'b T) -> &'a T; +} + +impl<'x, 'y, A> Test<'x, 'y, A> for () { + fn foo(&self, a: &'x A, b: &'y A) -> &'x A { + $0 +} +} +"#, + ); + } + + #[test] fn complete_without_name() { let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| { check_edit( @@ -1194,6 +1223,81 @@ impl Foo for Test { } #[test] + fn macro_generated_assoc_item() { + check_edit( + "fn method", + r#" +macro_rules! ty { () => { i32 } } +trait SomeTrait { type Output; } +impl SomeTrait for i32 { type Output = i64; } +macro_rules! define_method { + () => { + fn method(&mut self, params: <ty!() as SomeTrait>::Output); + }; +} +trait AnotherTrait { define_method!(); } +impl AnotherTrait for () { + $0 +} +"#, + r#" +macro_rules! ty { () => { i32 } } +trait SomeTrait { type Output; } +impl SomeTrait for i32 { type Output = i64; } +macro_rules! define_method { + () => { + fn method(&mut self, params: <ty!() as SomeTrait>::Output); + }; +} +trait AnotherTrait { define_method!(); } +impl AnotherTrait for () { + fn method(&mut self,params: <ty!()as SomeTrait>::Output) { + $0 +} +} +"#, + ); + } + + // FIXME: `T` in `ty!(T)` should be replaced by `PathTransform`. + #[test] + fn macro_generated_assoc_item2() { + check_edit( + "fn method", + r#" +macro_rules! ty { ($me:ty) => { $me } } +trait SomeTrait { type Output; } +impl SomeTrait for i32 { type Output = i64; } +macro_rules! define_method { + ($t:ty) => { + fn method(&mut self, params: <ty!($t) as SomeTrait>::Output); + }; +} +trait AnotherTrait<T: SomeTrait> { define_method!(T); } +impl AnotherTrait<i32> for () { + $0 +} +"#, + r#" +macro_rules! ty { ($me:ty) => { $me } } +trait SomeTrait { type Output; } +impl SomeTrait for i32 { type Output = i64; } +macro_rules! define_method { + ($t:ty) => { + fn method(&mut self, params: <ty!($t) as SomeTrait>::Output); + }; +} +trait AnotherTrait<T: SomeTrait> { define_method!(T); } +impl AnotherTrait<i32> for () { + fn method(&mut self,params: <ty!(T)as SomeTrait>::Output) { + $0 +} +} +"#, + ); + } + + #[test] fn includes_gat_generics() { check_edit( "type Ty", |