fix(completion): derive source scope from syntax node to be transformed

This commit is contained in:
Ryo Yoshida 2023-06-06 03:07:24 +09:00
parent 008f5065d1
commit d091991491
No known key found for this signature in database
GPG key ID: E25698A930586171
2 changed files with 79 additions and 12 deletions

View file

@ -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<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
where
Def::Ast: AstNode,

View file

@ -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)
@ -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: <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(