X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir%2Fsrc%2Fsemantics%2Fsource_to_def.rs;h=4672e7db40c25fe30a4c3cf245221dcdf3f9d23a;hb=b301b040f5781a9083348936369a01c37138756f;hp=495c84e65f43e0a73a9a5d48f6beff778084523a;hpb=7409880a07803c34590ad162d7854061145c6eae;p=rust.git diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 495c84e65f4..4672e7db40c 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -87,21 +87,22 @@ use base_db::FileId; use hir_def::{ + attr::AttrId, child_by_source::ChildBySource, dyn_map::DynMap, expr::{LabelId, PatId}, keys::{self, Key}, AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, - GenericDefId, GenericParamId, ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, - TypeAliasId, TypeParamId, UnionId, VariantId, + GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId, + TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, }; -use hir_expand::{name::AsName, AstId, HirFileId, MacroCallId, MacroDefId, MacroDefKind}; +use hir_expand::{name::AsName, HirFileId, MacroCallId}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use stdx::impl_from; use syntax::{ ast::{self, HasName}, - match_ast, AstNode, SyntaxNode, + AstNode, SyntaxNode, }; use crate::{db::HirDatabase, InFile}; @@ -131,13 +132,10 @@ impl SourceToDefCtx<'_, '_> { pub(super) fn module_to_def(&mut self, src: InFile) -> Option { let _p = profile::span("module_to_def"); - let parent_declaration = - src.syntax().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1).find_map( - |it| { - let m = ast::Module::cast(it.value.clone())?; - Some(it.with_value(m)) - }, - ); + let parent_declaration = src + .syntax() + .ancestors_with_macros_skip_attr_item(self.db.upcast()) + .find_map(|it| it.map(ast::Module::cast).transpose()); let parent_module = match parent_declaration { Some(parent_declaration) => self.module_to_def(parent_declaration), @@ -149,7 +147,7 @@ pub(super) fn module_to_def(&mut self, src: InFile) -> Option) -> Option { let map = self.dyn_map(src.as_ref())?; - map[keys::ATTR_MACRO].get(&src).copied() + map[keys::ATTR_MACRO_CALL].get(&src.value).copied() } pub(super) fn attr_to_derive_macro_call( &mut self, - item: InFile<&ast::Item>, + item: InFile<&ast::Adt>, src: InFile, - ) -> Option<&[Option]> { + ) -> Option<(AttrId, MacroCallId, &[Option])> { let map = self.dyn_map(item)?; - map[keys::DERIVE_MACRO].get(&src).map(AsRef::as_ref) + map[keys::DERIVE_MACRO_CALL] + .get(&src.value) + .map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids)) + } + pub(super) fn has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool { + self.dyn_map(adt).as_ref().map_or(false, |map| !map[keys::DERIVE_MACRO_CALL].is_empty()) } fn to_def( @@ -258,7 +261,7 @@ fn to_def( src: InFile, key: Key, ) -> Option { - self.dyn_map(src.as_ref())?[key].get(&src).copied() + self.dyn_map(src.as_ref())?[key].get(&src.value).copied() } fn dyn_map(&mut self, src: InFile<&Ast>) -> Option<&DynMap> { @@ -276,7 +279,7 @@ fn cache_for(&mut self, container: ChildContainer, file_id: HirFileId) -> &DynMa pub(super) fn type_param_to_def(&mut self, src: InFile) -> Option { let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::TYPE_PARAM].get(&src).copied() + dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| TypeParamId::from_unchecked(x)) } pub(super) fn lifetime_param_to_def( @@ -285,7 +288,7 @@ pub(super) fn lifetime_param_to_def( ) -> Option { let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::LIFETIME_PARAM].get(&src).copied() + dyn_map[keys::LIFETIME_PARAM].get(&src.value).copied() } pub(super) fn const_param_to_def( @@ -294,7 +297,7 @@ pub(super) fn const_param_to_def( ) -> Option { let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::CONST_PARAM].get(&src).copied() + dyn_map[keys::CONST_PARAM].get(&src.value).copied().map(|x| ConstParamId::from_unchecked(x)) } pub(super) fn generic_param_to_def( @@ -314,24 +317,22 @@ pub(super) fn generic_param_to_def( } } - pub(super) fn macro_to_def(&mut self, src: InFile) -> Option { - let makro = self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO].get(&src).copied()); - if let res @ Some(_) = makro { - return res; - } + pub(super) fn macro_to_def(&mut self, src: InFile) -> Option { + self.dyn_map(src.as_ref()).and_then(|it| match &src.value { + ast::Macro::MacroRules(value) => { + it[keys::MACRO_RULES].get(value).copied().map(MacroId::from) + } + ast::Macro::MacroDef(value) => it[keys::MACRO2].get(value).copied().map(MacroId::from), + }) + } - // Not all macros are recorded in the dyn map, only the ones behaving like items, so fall back - // for the non-item like definitions. - let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); - let ast_id = AstId::new(src.file_id, file_ast_id.upcast()); - let kind = MacroDefKind::Declarative(ast_id); - let file_id = src.file_id.original_file(self.db.upcast()); - let krate = self.file_to_def(file_id).get(0).copied()?.krate(); - Some(MacroDefId { krate, kind, local_inner: false }) + pub(super) fn proc_macro_to_def(&mut self, src: InFile) -> Option { + self.dyn_map(src.as_ref()) + .and_then(|it| it[keys::PROC_MACRO].get(&src.value).copied().map(MacroId::from)) } pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { + for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) { if let Some(res) = self.container_to_def(container) { return Some(res); } @@ -342,70 +343,62 @@ pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option) -> Option { - 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 cont = if let Some(item) = ast::Item::cast(container.value.clone()) { + 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::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::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) => { + } + ast::Item::Union(it) => { let def = self.union_to_def(container.with_value(it))?; VariantId::from(def).into() - }, - ast::Static(it) => { + } + ast::Item::Fn(it) => { + let def = self.fn_to_def(container.with_value(it))?; + DefWithBodyId::from(def).into() + } + ast::Item::Static(it) => { let def = self.static_to_def(container.with_value(it))?; DefWithBodyId::from(def).into() - }, - ast::Const(it) => { + } + ast::Item::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, } + } else { + let it = ast::Variant::cast(container.value)?; + let def = self.enum_variant_to_def(InFile::new(container.file_id, it))?; + VariantId::from(def).into() }; Some(cont) } fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { - let res: GenericDefId = match_ast! { - match (container.value) { - ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), - ast::Struct(it) => self.struct_to_def(container.with_value(it))?.into(), - ast::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), - ast::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), - ast::TypeAlias(it) => self.type_alias_to_def(container.with_value(it))?.into(), - ast::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), - _ => continue, + let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + for InFile { file_id, value } in ancestors { + let item = match ast::Item::cast(value) { + Some(it) => it, + None => continue, + }; + let res: GenericDefId = match item { + ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(), + ast::Item::TypeAlias(it) => { + self.type_alias_to_def(InFile::new(file_id, it))?.into() } + ast::Item::Impl(it) => self.impl_to_def(InFile::new(file_id, it))?.into(), + _ => continue, }; return Some(res); } @@ -413,14 +406,17 @@ fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) { - let res: DefWithBodyId = match_ast! { - match (container.value) { - ast::Const(it) => self.const_to_def(container.with_value(it))?.into(), - ast::Static(it) => self.static_to_def(container.with_value(it))?.into(), - ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), - _ => continue, - } + let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + for InFile { file_id, value } in ancestors { + let item = match ast::Item::cast(value) { + Some(it) => it, + None => continue, + }; + let res: DefWithBodyId = match item { + ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Static(it) => self.static_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), + _ => continue, }; return Some(res); }