Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/semantics/source_to_def.rs')
-rw-r--r--crates/hir/src/semantics/source_to_def.rs37
1 files changed, 23 insertions, 14 deletions
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 7f6c9af474..71ee0f6938 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -108,7 +108,7 @@ use span::FileId;
use stdx::impl_from;
use syntax::{
AstNode, AstPtr, SyntaxNode,
- ast::{self, HasName},
+ ast::{self, HasAttrs, HasName},
};
use tt::TextRange;
@@ -411,10 +411,25 @@ impl SourceToDefCtx<'_, '_> {
.map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids))
}
- pub(super) fn has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool {
+ // FIXME: Make this more fine grained! This should be a `adt_has_derives`!
+ pub(super) fn file_of_adt_has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool {
self.dyn_map(adt).as_ref().is_some_and(|map| !map[keys::DERIVE_MACRO_CALL].is_empty())
}
+ pub(super) fn derive_macro_calls<'slf>(
+ &'slf mut self,
+ adt: InFile<&ast::Adt>,
+ ) -> Option<impl Iterator<Item = (AttrId, MacroCallId, &'slf [Option<MacroCallId>])> + use<'slf>>
+ {
+ self.dyn_map(adt).as_ref().map(|&map| {
+ let dyn_map = &map[keys::DERIVE_MACRO_CALL];
+ adt.value
+ .attrs()
+ .filter_map(move |attr| dyn_map.get(&AstPtr::new(&attr)))
+ .map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids))
+ })
+ }
+
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
&mut self,
src: InFile<&Ast>,
@@ -616,14 +631,14 @@ impl SourceToDefCtx<'_, '_> {
match &item {
ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(),
ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(),
- ast::Item::TraitAlias(it) => {
- self.trait_alias_to_def(container.with_value(it))?.into()
- }
ast::Item::Impl(it) => self.impl_to_def(container.with_value(it))?.into(),
ast::Item::Enum(it) => self.enum_to_def(container.with_value(it))?.into(),
- ast::Item::TypeAlias(it) => {
- self.type_alias_to_def(container.with_value(it))?.into()
- }
+ ast::Item::TypeAlias(it) => ChildContainer::GenericDefId(
+ self.type_alias_to_def(container.with_value(it))?.into(),
+ ),
+ ast::Item::TraitAlias(it) => ChildContainer::GenericDefId(
+ self.trait_alias_to_def(container.with_value(it))?.into(),
+ ),
ast::Item::Struct(it) => {
let def = self.struct_to_def(container.with_value(it))?;
let is_in_body = it.field_list().is_some_and(|it| {
@@ -723,11 +738,9 @@ pub(crate) enum ChildContainer {
DefWithBodyId(DefWithBodyId),
ModuleId(ModuleId),
TraitId(TraitId),
- TraitAliasId(TraitAliasId),
ImplId(ImplId),
EnumId(EnumId),
VariantId(VariantId),
- TypeAliasId(TypeAliasId),
/// XXX: this might be the same def as, for example an `EnumId`. However,
/// here the children are generic parameters, and not, eg enum variants.
GenericDefId(GenericDefId),
@@ -736,11 +749,9 @@ impl_from! {
DefWithBodyId,
ModuleId,
TraitId,
- TraitAliasId,
ImplId,
EnumId,
VariantId,
- TypeAliasId,
GenericDefId
for ChildContainer
}
@@ -752,11 +763,9 @@ impl ChildContainer {
ChildContainer::DefWithBodyId(it) => it.child_by_source(db, file_id),
ChildContainer::ModuleId(it) => it.child_by_source(db, file_id),
ChildContainer::TraitId(it) => it.child_by_source(db, file_id),
- ChildContainer::TraitAliasId(_) => DynMap::default(),
ChildContainer::ImplId(it) => it.child_by_source(db, file_id),
ChildContainer::EnumId(it) => it.child_by_source(db, file_id),
ChildContainer::VariantId(it) => it.child_by_source(db, file_id),
- ChildContainer::TypeAliasId(_) => DynMap::default(),
ChildContainer::GenericDefId(it) => it.child_by_source(db, file_id),
}
}