9180: fix: fix some IDE functionality inside attribute macros r=jonas-schievink a=jonas-schievink

In `SourceToDefCtx::find_container`, we might encounter a container that has an attribute macro. We need to skip that item, instead of bailing out and creating an empty `Resolver`, otherwise all names in the macro stay unresolved.

Part of https://github.com/rust-analyzer/rust-analyzer/issues/9142

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-06-08 19:01:23 +00:00 committed by GitHub
commit 4e3769fbf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -211,62 +211,68 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
let res: ChildContainer = match_ast! {
match (container.value) {
ast::Module(it) => {
let def = self.module_to_def(container.with_value(it))?;
def.into()
},
ast::Trait(it) => {
let def = self.trait_to_def(container.with_value(it))?;
def.into()
},
ast::Impl(it) => {
let def = self.impl_to_def(container.with_value(it))?;
def.into()
},
ast::Fn(it) => {
let def = self.fn_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::Struct(it) => {
let def = self.struct_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
ast::Enum(it) => {
let def = self.enum_to_def(container.with_value(it))?;
def.into()
},
ast::Union(it) => {
let def = self.union_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
ast::Static(it) => {
let def = self.static_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::Const(it) => {
let def = self.const_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::TypeAlias(it) => {
let def = self.type_alias_to_def(container.with_value(it))?;
def.into()
},
ast::Variant(it) => {
let def = self.enum_variant_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
_ => continue,
}
};
return Some(res);
if let Some(res) = self.container_to_def(container) {
return Some(res);
}
}
let def = self.file_to_def(src.file_id.original_file(self.db.upcast())).get(0).copied()?;
Some(def.into())
}
fn container_to_def(&mut self, container: InFile<SyntaxNode>) -> Option<ChildContainer> {
let cont = match_ast! {
match (container.value) {
ast::Module(it) => {
let def = self.module_to_def(container.with_value(it))?;
def.into()
},
ast::Trait(it) => {
let def = self.trait_to_def(container.with_value(it))?;
def.into()
},
ast::Impl(it) => {
let def = self.impl_to_def(container.with_value(it))?;
def.into()
},
ast::Fn(it) => {
let def = self.fn_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::Struct(it) => {
let def = self.struct_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
ast::Enum(it) => {
let def = self.enum_to_def(container.with_value(it))?;
def.into()
},
ast::Union(it) => {
let def = self.union_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
ast::Static(it) => {
let def = self.static_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::Const(it) => {
let def = self.const_to_def(container.with_value(it))?;
DefWithBodyId::from(def).into()
},
ast::TypeAlias(it) => {
let def = self.type_alias_to_def(container.with_value(it))?;
def.into()
},
ast::Variant(it) => {
let def = self.enum_variant_to_def(container.with_value(it))?;
VariantId::from(def).into()
},
_ => return None,
}
};
Some(cont)
}
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
let res: GenericDefId = match_ast! {