Skip to content

Commit

Permalink
fix(completion): derive source scope from syntax node to be transformed
Browse files Browse the repository at this point in the history
  • Loading branch information
lowr committed Jun 6, 2023
1 parent 55b1fbb commit 7df5768
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 12 deletions.
10 changes: 0 additions & 10 deletions crates/hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
where
Def::Ast: AstNode,
Expand Down
81 changes: 79 additions & 2 deletions crates/ide-completion/src/completions/item_list/trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -1193,6 +1195,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(
Expand Down

0 comments on commit 7df5768

Please sign in to comment.