From a6a623dfbb40b79cac7857165114fa11a25e4e1f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 29 Feb 2020 16:57:56 +0100 Subject: Small cleanup --- crates/ra_hir/src/source_binder.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 4353e25ac..439a4d5db 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -101,15 +101,7 @@ impl SourceBinder { } fn child_by_source(&mut self, db: &impl HirDatabase, container: ChildContainer) -> &DynMap { - self.child_by_source_cache.entry(container).or_insert_with(|| match container { - ChildContainer::DefWithBodyId(it) => it.child_by_source(db), - ChildContainer::ModuleId(it) => it.child_by_source(db), - ChildContainer::TraitId(it) => it.child_by_source(db), - ChildContainer::ImplId(it) => it.child_by_source(db), - ChildContainer::EnumId(it) => it.child_by_source(db), - ChildContainer::VariantId(it) => it.child_by_source(db), - ChildContainer::GenericDefId(it) => it.child_by_source(db), - }) + self.child_by_source_cache.entry(container).or_insert_with(|| container.child_by_source(db)) } } @@ -145,6 +137,20 @@ impl_froms! { GenericDefId } +impl ChildContainer { + fn child_by_source(self, db: &impl HirDatabase) -> DynMap { + match self { + ChildContainer::DefWithBodyId(it) => it.child_by_source(db), + ChildContainer::ModuleId(it) => it.child_by_source(db), + ChildContainer::TraitId(it) => it.child_by_source(db), + ChildContainer::ImplId(it) => it.child_by_source(db), + ChildContainer::EnumId(it) => it.child_by_source(db), + ChildContainer::VariantId(it) => it.child_by_source(db), + ChildContainer::GenericDefId(it) => it.child_by_source(db), + } + } +} + pub(crate) trait ToIdByKey: Sized + AstNode + 'static { type ID: Sized + Copy + 'static; const KEY: Key; -- cgit v1.2.3 From 28332d9b63ed58ecc33604d04488f07ff75a553d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 29 Feb 2020 18:32:18 +0100 Subject: Simplify SourceBinder --- crates/ra_hir/src/code_model.rs | 1 + crates/ra_hir/src/from_id.rs | 12 +- crates/ra_hir/src/lib.rs | 1 - crates/ra_hir/src/semantics.rs | 101 ++++------ crates/ra_hir/src/semantics/source_to_def.rs | 271 +++++++++++++++++++++++++ crates/ra_hir/src/source_binder.rs | 284 --------------------------- 6 files changed, 321 insertions(+), 349 deletions(-) create mode 100644 crates/ra_hir/src/semantics/source_to_def.rs delete mode 100644 crates/ra_hir/src/source_binder.rs diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index efc3502d0..a9615a3b7 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -778,6 +778,7 @@ impl GenericDef { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Local { + // TODO: ID, pub(crate) parent: DefWithBody, pub(crate) pat_id: PatId, } diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 3aa7c4870..88540fbf2 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -4,12 +4,12 @@ //! are splitting the hir. use hir_def::{ - AdtId, AssocItemId, AttrDefId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId, - StructFieldId, VariantId, + expr::PatId, AdtId, AssocItemId, AttrDefId, DefWithBodyId, EnumVariantId, GenericDefId, + ModuleDefId, StructFieldId, VariantId, }; use crate::{ - Adt, AssocItem, AttrDef, DefWithBody, EnumVariant, GenericDef, ModuleDef, StructField, + Adt, AssocItem, AttrDef, DefWithBody, EnumVariant, GenericDef, Local, ModuleDef, StructField, VariantDef, }; @@ -222,3 +222,9 @@ impl From for GenericDefId { } } } + +impl From<(DefWithBodyId, PatId)> for Local { + fn from((parent, pat_id): (DefWithBodyId, PatId)) -> Self { + Local { parent: parent.into(), pat_id } + } +} diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3aa964fb6..cefbd80e6 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -29,7 +29,6 @@ macro_rules! impl_froms { mod semantics; pub mod db; mod source_analyzer; -mod source_binder; pub mod diagnostics; diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 4a9cb7b3e..60392947e 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -1,32 +1,33 @@ //! See `Semantics`. +mod source_to_def; + use std::{cell::RefCell, fmt, iter::successors}; use hir_def::{ resolver::{self, HasResolver, Resolver}, - DefWithBodyId, TraitId, + TraitId, }; +use hir_expand::ExpansionInfo; use ra_db::{FileId, FileRange}; +use ra_prof::profile; use ra_syntax::{ - algo::skip_trivia_token, ast, match_ast, AstNode, Direction, SyntaxNode, SyntaxToken, - TextRange, TextUnit, + algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit, }; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ db::HirDatabase, + semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, - source_binder::{ChildContainer, SourceBinder}, Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, }; -use hir_expand::ExpansionInfo; -use ra_prof::profile; /// Primary API to get semantic information, like types, from syntax trees. pub struct Semantics<'db, DB> { pub db: &'db DB, - sb: RefCell, + s2d_cache: RefCell, cache: RefCell>, } @@ -38,8 +39,7 @@ impl fmt::Debug for Semantics<'_, DB> { impl<'db, DB: HirDatabase> Semantics<'db, DB> { pub fn new(db: &DB) -> Semantics { - let sb = RefCell::new(SourceBinder::new()); - Semantics { db, sb, cache: RefCell::default() } + Semantics { db, s2d_cache: Default::default(), cache: Default::default() } } pub fn parse(&self, file_id: FileId) -> ast::SourceFile { @@ -136,13 +136,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { // FIXME: use this instead? // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option; - pub fn to_def(&self, src: &T) -> Option { + pub fn to_def(&self, src: &T) -> Option { + let src = self.find_file(src.syntax().clone()).with_value(src).cloned(); T::to_def(self, src) } + fn with_ctx) -> T, T>(&self, f: F) -> T { + let mut cache = self.s2d_cache.borrow_mut(); + let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache }; + f(&mut ctx) + } + pub fn to_module_def(&self, file: FileId) -> Option { - let mut sb = self.sb.borrow_mut(); - sb.to_module_def(self.db, file) + self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) } pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db, DB> { @@ -176,7 +182,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { fn analyze2(&self, src: InFile<&SyntaxNode>, offset: Option) -> SourceAnalyzer { let _p = profile("Semantics::analyze2"); - let container = match self.sb.borrow_mut().find_container(self.db, src) { + let container = match self.with_ctx(|ctx| ctx.find_container(src)) { Some(it) => it, None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src), }; @@ -233,68 +239,41 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { } } -pub trait ToDef: Sized + AstNode + 'static { +pub trait ToDef: AstNode + Clone { type Def; - fn to_def(sema: &Semantics, src: &Self) -> Option; + + fn to_def(sema: &Semantics, src: InFile) -> Option; } macro_rules! to_def_impls { - ($(($def:path, $ast:path)),* ,) => {$( + ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( impl ToDef for $ast { type Def = $def; - fn to_def(sema: &Semantics, src: &Self) - -> Option - { - let src = sema.find_file(src.syntax().clone()).with_value(src); - sema.sb.borrow_mut().to_id(sema.db, src.cloned()).map(Into::into) + fn to_def(sema: &Semantics, src: InFile) -> Option { + sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) } } )*} } to_def_impls![ - (crate::Module, ast::Module), - (crate::Struct, ast::StructDef), - (crate::Enum, ast::EnumDef), - (crate::Union, ast::UnionDef), - (crate::Trait, ast::TraitDef), - (crate::ImplBlock, ast::ImplBlock), - (crate::TypeAlias, ast::TypeAliasDef), - (crate::Const, ast::ConstDef), - (crate::Static, ast::StaticDef), - (crate::Function, ast::FnDef), - (crate::StructField, ast::RecordFieldDef), - (crate::EnumVariant, ast::EnumVariant), - (crate::TypeParam, ast::TypeParam), - (crate::MacroDef, ast::MacroCall), // this one is dubious, not all calls are macros + (crate::Module, ast::Module, module_to_def), + (crate::Struct, ast::StructDef, struct_to_def), + (crate::Enum, ast::EnumDef, enum_to_def), + (crate::Union, ast::UnionDef, union_to_def), + (crate::Trait, ast::TraitDef, trait_to_def), + (crate::ImplBlock, ast::ImplBlock, impl_to_def), + (crate::TypeAlias, ast::TypeAliasDef, type_alias_to_def), + (crate::Const, ast::ConstDef, const_to_def), + (crate::Static, ast::StaticDef, static_to_def), + (crate::Function, ast::FnDef, fn_to_def), + (crate::StructField, ast::RecordFieldDef, record_field_to_def), + (crate::EnumVariant, ast::EnumVariant, enum_variant_to_def), + (crate::TypeParam, ast::TypeParam, type_param_to_def), + (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros + (crate::Local, ast::BindPat, bind_pat_to_def), ]; -impl ToDef for ast::BindPat { - type Def = Local; - - fn to_def(sema: &Semantics, src: &Self) -> Option { - let src = sema.find_file(src.syntax().clone()).with_value(src); - let file_id = src.file_id; - let mut sb = sema.sb.borrow_mut(); - let db = sema.db; - let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { - let res = match_ast! { - match it { - ast::ConstDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::StaticDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - _ => return None, - } - }; - Some(res) - })?; - let (_body, source_map) = db.body_with_source_map(parent); - let src = src.cloned().map(ast::Pat::from); - let pat_id = source_map.node_pat(src.as_ref())?; - Some(Local { parent: parent.into(), pat_id }) - } -} - fn find_root(node: &SyntaxNode) -> SyntaxNode { node.ancestors().last().unwrap() } diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs new file mode 100644 index 000000000..303610dc4 --- /dev/null +++ b/crates/ra_hir/src/semantics/source_to_def.rs @@ -0,0 +1,271 @@ +//! Maps *syntax* of various definitions to their semantic ids. + +use hir_def::{ + child_by_source::ChildBySource, + dyn_map::DynMap, + expr::PatId, + keys::{self, Key}, + ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, + StaticId, StructFieldId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, +}; +use hir_expand::{name::AsName, AstId, MacroDefKind}; +use ra_db::FileId; +use ra_prof::profile; +use ra_syntax::{ + ast::{self, NameOwner}, + match_ast, AstNode, SyntaxNode, +}; +use rustc_hash::FxHashMap; + +use crate::{db::HirDatabase, InFile, MacroDefId}; + +pub(super) type SourceToDefCache = FxHashMap; + +pub(super) struct SourceToDefCtx<'a, DB> { + pub(super) db: DB, + pub(super) cache: &'a mut SourceToDefCache, +} + +impl SourceToDefCtx<'_, &'_ DB> { + pub(super) fn file_to_def(&mut self, file: FileId) -> Option { + let _p = profile("SourceBinder::to_module_def"); + let (krate, local_id) = self.db.relevant_crates(file).iter().find_map(|&crate_id| { + let crate_def_map = self.db.crate_def_map(crate_id); + let local_id = crate_def_map.modules_for_file(file).next()?; + Some((crate_id, local_id)) + })?; + Some(ModuleId { krate, local_id }) + } + + pub(super) fn module_to_def(&mut self, src: InFile) -> Option { + let _p = profile("module_to_def"); + let parent_declaration = src + .as_ref() + .map(|it| it.syntax()) + .cloned() + .ancestors_with_macros(self.db) + .skip(1) + .find_map(|it| { + let m = ast::Module::cast(it.value.clone())?; + Some(it.with_value(m)) + }); + + let parent_module = match parent_declaration { + Some(parent_declaration) => self.module_to_def(parent_declaration), + None => { + let file_id = src.file_id.original_file(self.db); + self.file_to_def(file_id) + } + }?; + + let child_name = src.value.name()?.as_name(); + let def_map = self.db.crate_def_map(parent_module.krate); + let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; + Some(ModuleId { krate: parent_module.krate, local_id: child_id }) + } + + pub(super) fn trait_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::TRAIT) + } + pub(super) fn impl_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::IMPL) + } + pub(super) fn fn_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::FUNCTION) + } + pub(super) fn struct_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::STRUCT) + } + pub(super) fn enum_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::ENUM) + } + pub(super) fn union_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::UNION) + } + pub(super) fn static_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::STATIC) + } + pub(super) fn const_to_def(&mut self, src: InFile) -> Option { + self.to_def(src, keys::CONST) + } + pub(super) fn type_alias_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::TYPE_ALIAS) + } + //TODO: tuple field + pub(super) fn record_field_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::RECORD_FIELD) + } + pub(super) fn enum_variant_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::ENUM_VARIANT) + } + pub(super) fn bind_pat_to_def( + &mut self, + src: InFile, + ) -> Option<(DefWithBodyId, PatId)> { + let container = self.find_pat_container(src.as_ref().map(|it| it.syntax()))?; + let (_body, source_map) = self.db.body_with_source_map(container); + let src = src.map(ast::Pat::from); + let pat_id = source_map.node_pat(src.as_ref())?; + Some((container, pat_id)) + } + + fn to_def( + &mut self, + src: InFile, + key: Key, + ) -> Option { + let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; + let db = self.db; + let dyn_map = + &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); + dyn_map[key].get(&src).copied() + } + + pub(super) fn type_param_to_def(&mut self, src: InFile) -> Option { + let container: ChildContainer = + self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into(); + let db = self.db; + let dyn_map = + &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); + dyn_map[keys::TYPE_PARAM].get(&src).copied() + } + + // FIXME: use DynMap as well? + pub(super) fn macro_call_to_def(&mut self, src: InFile) -> Option { + let kind = MacroDefKind::Declarative; + let file_id = src.file_id.original_file(self.db); + let krate = self.file_to_def(file_id)?.krate; + let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); + let ast_id = Some(AstId::new(src.file_id, file_ast_id)); + Some(MacroDefId { krate: Some(krate), ast_id, kind }) + } + + pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { + for container in src.cloned().ancestors_with_macros(self.db).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::TraitDef(it) => { + let def = self.trait_to_def(container.with_value(it))?; + def.into() + }, + ast::ImplBlock(it) => { + let def = self.impl_to_def(container.with_value(it))?; + def.into() + }, + ast::FnDef(it) => { + let def = self.fn_to_def(container.with_value(it))?; + DefWithBodyId::from(def).into() + }, + ast::StructDef(it) => { + let def = self.struct_to_def(container.with_value(it))?; + VariantId::from(def).into() + }, + ast::EnumDef(it) => { + let def = self.enum_to_def(container.with_value(it))?; + def.into() + }, + ast::UnionDef(it) => { + let def = self.union_to_def(container.with_value(it))?; + VariantId::from(def).into() + }, + ast::StaticDef(it) => { + let def = self.static_to_def(container.with_value(it))?; + DefWithBodyId::from(def).into() + }, + ast::ConstDef(it) => { + let def = self.const_to_def(container.with_value(it))?; + DefWithBodyId::from(def).into() + }, + _ => continue, + } + }; + return Some(res); + } + + let def = self.file_to_def(src.file_id.original_file(self.db))?; + Some(def.into()) + } + + fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option { + for container in src.cloned().ancestors_with_macros(self.db).skip(1) { + let res: GenericDefId = match_ast! { + match (container.value) { + ast::FnDef(it) => { self.fn_to_def(container.with_value(it))?.into() }, + ast::StructDef(it) => { self.struct_to_def(container.with_value(it))?.into() }, + ast::EnumDef(it) => { self.enum_to_def(container.with_value(it))?.into() }, + ast::TraitDef(it) => { self.trait_to_def(container.with_value(it))?.into() }, + ast::TypeAliasDef(it) => { self.type_alias_to_def(container.with_value(it))?.into() }, + ast::ImplBlock(it) => { self.impl_to_def(container.with_value(it))?.into() }, + _ => continue, + } + }; + return Some(res); + } + None + } + + fn find_pat_container(&mut self, src: InFile<&SyntaxNode>) -> Option { + for container in src.cloned().ancestors_with_macros(self.db).skip(1) { + let res: DefWithBodyId = match_ast! { + match (container.value) { + ast::ConstDef(it) => { self.const_to_def(container.with_value(it))?.into() }, + ast::StaticDef(it) => { self.static_to_def(container.with_value(it))?.into() }, + ast::FnDef(it) => { self.fn_to_def(container.with_value(it))?.into() }, + _ => continue, + } + }; + return Some(res); + } + None + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum ChildContainer { + DefWithBodyId(DefWithBodyId), + ModuleId(ModuleId), + TraitId(TraitId), + ImplId(ImplId), + EnumId(EnumId), + VariantId(VariantId), + /// XXX: this might be the same def as, for example an `EnumId`. However, + /// here the children generic parameters, and not, eg enum variants. + GenericDefId(GenericDefId), +} +impl_froms! { + ChildContainer: + DefWithBodyId, + ModuleId, + TraitId, + ImplId, + EnumId, + VariantId, + GenericDefId +} + +impl ChildContainer { + fn child_by_source(self, db: &impl HirDatabase) -> DynMap { + match self { + ChildContainer::DefWithBodyId(it) => it.child_by_source(db), + ChildContainer::ModuleId(it) => it.child_by_source(db), + ChildContainer::TraitId(it) => it.child_by_source(db), + ChildContainer::ImplId(it) => it.child_by_source(db), + ChildContainer::EnumId(it) => it.child_by_source(db), + ChildContainer::VariantId(it) => it.child_by_source(db), + ChildContainer::GenericDefId(it) => it.child_by_source(db), + } + } +} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs deleted file mode 100644 index 439a4d5db..000000000 --- a/crates/ra_hir/src/source_binder.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! `SourceBinder` is the main entry point for getting info about source code. -//! It's main task is to map source syntax trees to hir-level IDs. - -use hir_def::{ - child_by_source::ChildBySource, - dyn_map::DynMap, - keys::{self, Key}, - ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, - StaticId, StructFieldId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, -}; -use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; -use ra_db::FileId; -use ra_prof::profile; -use ra_syntax::{ - ast::{self, NameOwner}, - match_ast, AstNode, SyntaxNode, -}; -use rustc_hash::FxHashMap; - -use crate::{db::HirDatabase, Module}; - -pub(crate) struct SourceBinder { - child_by_source_cache: FxHashMap, -} - -impl SourceBinder { - pub(crate) fn new() -> SourceBinder { - SourceBinder { child_by_source_cache: FxHashMap::default() } - } - - pub(crate) fn to_module_def(&mut self, db: &impl HirDatabase, file: FileId) -> Option { - let _p = profile("SourceBinder::to_module_def"); - let (krate, local_id) = db.relevant_crates(file).iter().find_map(|&crate_id| { - let crate_def_map = db.crate_def_map(crate_id); - let local_id = crate_def_map.modules_for_file(file).next()?; - Some((crate_id, local_id)) - })?; - Some(Module { id: ModuleId { krate, local_id } }) - } - - pub(crate) fn to_id( - &mut self, - db: &impl HirDatabase, - src: InFile, - ) -> Option { - T::to_id(db, self, src) - } - - pub(crate) fn find_container( - &mut self, - db: &impl HirDatabase, - src: InFile<&SyntaxNode>, - ) -> Option { - for container in src.cloned().ancestors_with_macros(db).skip(1) { - let res: ChildContainer = match_ast! { - match (container.value) { - ast::TraitDef(it) => { - let def: TraitId = self.to_id(db, container.with_value(it))?; - def.into() - }, - ast::ImplBlock(it) => { - let def: ImplId = self.to_id(db, container.with_value(it))?; - def.into() - }, - ast::FnDef(it) => { - let def: FunctionId = self.to_id(db, container.with_value(it))?; - DefWithBodyId::from(def).into() - }, - ast::StaticDef(it) => { - let def: StaticId = self.to_id(db, container.with_value(it))?; - DefWithBodyId::from(def).into() - }, - ast::ConstDef(it) => { - let def: ConstId = self.to_id(db, container.with_value(it))?; - DefWithBodyId::from(def).into() - }, - ast::EnumDef(it) => { - let def: EnumId = self.to_id(db, container.with_value(it))?; - def.into() - }, - ast::StructDef(it) => { - let def: StructId = self.to_id(db, container.with_value(it))?; - VariantId::from(def).into() - }, - ast::UnionDef(it) => { - let def: UnionId = self.to_id(db, container.with_value(it))?; - VariantId::from(def).into() - }, - ast::Module(it) => { - let def: ModuleId = self.to_id(db, container.with_value(it))?; - def.into() - }, - _ => { continue }, - } - }; - return Some(res); - } - - let c = self.to_module_def(db, src.file_id.original_file(db))?; - Some(c.id.into()) - } - - fn child_by_source(&mut self, db: &impl HirDatabase, container: ChildContainer) -> &DynMap { - self.child_by_source_cache.entry(container).or_insert_with(|| container.child_by_source(db)) - } -} - -pub(crate) trait ToId: Sized { - type ID: Sized + Copy + 'static; - fn to_id( - db: &DB, - sb: &mut SourceBinder, - src: InFile, - ) -> Option; -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub(crate) enum ChildContainer { - DefWithBodyId(DefWithBodyId), - ModuleId(ModuleId), - TraitId(TraitId), - ImplId(ImplId), - EnumId(EnumId), - VariantId(VariantId), - /// XXX: this might be the same def as, for example an `EnumId`. However, - /// here the children generic parameters, and not, eg enum variants. - GenericDefId(GenericDefId), -} -impl_froms! { - ChildContainer: - DefWithBodyId, - ModuleId, - TraitId, - ImplId, - EnumId, - VariantId, - GenericDefId -} - -impl ChildContainer { - fn child_by_source(self, db: &impl HirDatabase) -> DynMap { - match self { - ChildContainer::DefWithBodyId(it) => it.child_by_source(db), - ChildContainer::ModuleId(it) => it.child_by_source(db), - ChildContainer::TraitId(it) => it.child_by_source(db), - ChildContainer::ImplId(it) => it.child_by_source(db), - ChildContainer::EnumId(it) => it.child_by_source(db), - ChildContainer::VariantId(it) => it.child_by_source(db), - ChildContainer::GenericDefId(it) => it.child_by_source(db), - } - } -} - -pub(crate) trait ToIdByKey: Sized + AstNode + 'static { - type ID: Sized + Copy + 'static; - const KEY: Key; -} - -impl ToId for T { - type ID = ::ID; - fn to_id( - db: &DB, - sb: &mut SourceBinder, - src: InFile, - ) -> Option { - let container = sb.find_container(db, src.as_ref().map(|it| it.syntax()))?; - let dyn_map = - &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container { - ChildContainer::DefWithBodyId(it) => it.child_by_source(db), - ChildContainer::ModuleId(it) => it.child_by_source(db), - ChildContainer::TraitId(it) => it.child_by_source(db), - ChildContainer::ImplId(it) => it.child_by_source(db), - ChildContainer::EnumId(it) => it.child_by_source(db), - ChildContainer::VariantId(it) => it.child_by_source(db), - ChildContainer::GenericDefId(it) => it.child_by_source(db), - }); - dyn_map[T::KEY].get(&src).copied() - } -} - -macro_rules! to_id_key_impls { - ($(($id:ident, $ast:path, $key:path)),* ,) => {$( - impl ToIdByKey for $ast { - type ID = $id; - const KEY: Key = $key; - } - )*} -} - -to_id_key_impls![ - (StructId, ast::StructDef, keys::STRUCT), - (UnionId, ast::UnionDef, keys::UNION), - (EnumId, ast::EnumDef, keys::ENUM), - (TraitId, ast::TraitDef, keys::TRAIT), - (FunctionId, ast::FnDef, keys::FUNCTION), - (StaticId, ast::StaticDef, keys::STATIC), - (ConstId, ast::ConstDef, keys::CONST), - (TypeAliasId, ast::TypeAliasDef, keys::TYPE_ALIAS), - (ImplId, ast::ImplBlock, keys::IMPL), - (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), - (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), -]; - -// FIXME: use DynMap as well? -impl ToId for ast::MacroCall { - type ID = MacroDefId; - fn to_id( - db: &DB, - sb: &mut SourceBinder, - src: InFile, - ) -> Option { - let kind = MacroDefKind::Declarative; - - let krate = sb.to_module_def(db, src.file_id.original_file(db))?.id.krate; - - let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value))); - - Some(MacroDefId { krate: Some(krate), ast_id, kind }) - } -} - -impl ToId for ast::TypeParam { - type ID = TypeParamId; - - fn to_id( - db: &DB, - sb: &mut SourceBinder, - src: InFile, - ) -> Option { - let file_id = src.file_id; - let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { - let res = match_ast! { - match it { - ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::StructDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::EnumDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::TraitDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::TypeAliasDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - ast::ImplBlock(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, - _ => return None, - } - }; - Some(res) - })?; - sb.child_by_source(db, parent.into())[keys::TYPE_PARAM].get(&src).copied() - } -} - -impl ToId for ast::Module { - type ID = ModuleId; - - fn to_id( - db: &DB, - sb: &mut SourceBinder, - src: InFile, - ) -> Option { - { - let _p = profile("ast::Module::to_def"); - let parent_declaration = src - .as_ref() - .map(|it| it.syntax()) - .cloned() - .ancestors_with_macros(db) - .skip(1) - .find_map(|it| { - let m = ast::Module::cast(it.value.clone())?; - Some(it.with_value(m)) - }); - - let parent_module = match parent_declaration { - Some(parent_declaration) => sb.to_id(db, parent_declaration)?, - None => { - let file_id = src.file_id.original_file(db); - sb.to_module_def(db, file_id)?.id - } - }; - - let child_name = src.value.name()?.as_name(); - let def_map = db.crate_def_map(parent_module.krate); - let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; - Some(ModuleId { krate: parent_module.krate, local_id: child_id }) - } - } -} -- cgit v1.2.3 From 14ea21617ab510daa4f88b0f7c93fdfd2d36e42d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 29 Feb 2020 18:34:34 +0100 Subject: Minor --- crates/ra_hir/src/code_model.rs | 7 +++---- crates/ra_hir/src/from_id.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a9615a3b7..034fb7cfa 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -778,8 +778,7 @@ impl GenericDef { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Local { - // TODO: ID, - pub(crate) parent: DefWithBody, + pub(crate) parent: DefWithBodyId, pub(crate) pat_id: PatId, } @@ -808,11 +807,11 @@ impl Local { } pub fn parent(self, _db: &impl HirDatabase) -> DefWithBody { - self.parent + self.parent.into() } pub fn module(self, db: &impl HirDatabase) -> Module { - self.parent.module(db) + self.parent(db).module(db) } pub fn ty(self, db: &impl HirDatabase) -> Type { diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 88540fbf2..cbfa91d6c 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -225,6 +225,6 @@ impl From for GenericDefId { impl From<(DefWithBodyId, PatId)> for Local { fn from((parent, pat_id): (DefWithBodyId, PatId)) -> Self { - Local { parent: parent.into(), pat_id } + Local { parent, pat_id } } } -- cgit v1.2.3 From 7f09083c6ff3cb3499b140ffe85f83a06f685aed Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 29 Feb 2020 18:35:45 +0100 Subject: Handle tuple fields as well --- crates/ra_hir/src/semantics.rs | 1 + crates/ra_hir/src/semantics/source_to_def.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 60392947e..74901e318 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -268,6 +268,7 @@ to_def_impls![ (crate::Static, ast::StaticDef, static_to_def), (crate::Function, ast::FnDef, fn_to_def), (crate::StructField, ast::RecordFieldDef, record_field_to_def), + (crate::StructField, ast::TupleFieldDef, tuple_field_to_def), (crate::EnumVariant, ast::EnumVariant, enum_variant_to_def), (crate::TypeParam, ast::TypeParam, type_param_to_def), (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs index 303610dc4..884b535b2 100644 --- a/crates/ra_hir/src/semantics/source_to_def.rs +++ b/crates/ra_hir/src/semantics/source_to_def.rs @@ -94,13 +94,18 @@ impl SourceToDefCtx<'_, &'_ DB> { ) -> Option { self.to_def(src, keys::TYPE_ALIAS) } - //TODO: tuple field pub(super) fn record_field_to_def( &mut self, src: InFile, ) -> Option { self.to_def(src, keys::RECORD_FIELD) } + pub(super) fn tuple_field_to_def( + &mut self, + src: InFile, + ) -> Option { + self.to_def(src, keys::TUPLE_FIELD) + } pub(super) fn enum_variant_to_def( &mut self, src: InFile, -- cgit v1.2.3