From d091991491631faab8a13d7c119575d4a9f7316d Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Tue, 6 Jun 2023 03:07:24 +0900 Subject: [PATCH] fix(completion): derive source scope from syntax node to be transformed --- crates/hir/src/semantics.rs | 10 --- .../src/completions/item_list/trait_impl.rs | 81 ++++++++++++++++++- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 2d2b00b147..36ded659b4 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -483,10 +483,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.scope_at_offset(node, offset) } - pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { - self.imp.scope_for_def(def) - } - pub fn assert_contains_node(&self, node: &SyntaxNode) { self.imp.assert_contains_node(node) } @@ -1307,12 +1303,6 @@ impl<'db> SemanticsImpl<'db> { ) } - fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { - let file_id = self.db.lookup_intern_trait(def.id).id.file_id(); - let resolver = def.id.resolver(self.db.upcast()); - SemanticsScope { db: self.db, file_id, resolver } - } - fn source(&self, def: Def) -> Option> where Def::Ast: AstNode, 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 664aa7b839..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 { - 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) @@ -1220,6 +1222,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: ::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: ::Output); + }; +} +trait AnotherTrait { define_method!(); } +impl AnotherTrait for () { + fn method(&mut self,params: ::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: ::Output); + }; +} +trait AnotherTrait { define_method!(T); } +impl AnotherTrait 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: ::Output); + }; +} +trait AnotherTrait { define_method!(T); } +impl AnotherTrait for () { + fn method(&mut self,params: ::Output) { + $0 +} +} +"#, + ); + } + #[test] fn includes_gat_generics() { check_edit(