From 64c21ed19594b323e72605ba8c5dd4c6eee433f6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 17:39:58 +0300 Subject: Switch type aliases to new sources --- crates/ra_hir/src/code_model.rs | 28 +++++---- crates/ra_hir/src/code_model/src.rs | 2 +- crates/ra_hir/src/from_source.rs | 112 +++++++++++++++++++++++------------- 3 files changed, 88 insertions(+), 54 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index c49190a0f..b8d48a500 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -13,7 +13,7 @@ use hir_def::{ traits::TraitData, type_ref::{Mutability, TypeRef}, AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId, - LocalStructFieldId, Lookup, ModuleId, UnionId, + LocalStructFieldId, Lookup, ModuleId, TypeAliasContainerId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -954,30 +954,34 @@ pub struct TypeAlias { impl TypeAlias { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { Some(self.module(db).krate()) } - /// The containing impl block, if this is a method. + /// The containing impl block, if this is a type alias. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - ImplBlock::containing(db, self.into()) + match self.container(db) { + Some(Container::ImplBlock(it)) => Some(it), + _ => None, + } } - /// The containing trait, if this is a trait method definition. + /// The containing trait, if this is a trait type alias definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) + match self.container(db) { + Some(Container::Trait(it)) => Some(it), + _ => None, + } } pub fn container(self, db: &impl DefDatabase) -> Option { - if let Some(impl_block) = self.impl_block(db) { - Some(impl_block.into()) - } else if let Some(trait_) = self.parent_trait(db) { - Some(trait_.into()) - } else { - None + match self.id.lookup(db).container { + TypeAliasContainerId::TraitId(it) => Some(Container::Trait(it.into())), + TypeAliasContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + TypeAliasContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 91cab7414..04675e08e 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -138,7 +138,7 @@ impl HasSource for Trait { impl HasSource for TypeAlias { type Ast = ast::TypeAliasDef; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for MacroDef { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 303d5f138..f5fdaafa3 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -4,7 +4,7 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, - match_ast, AstPtr, + match_ast, AstPtr, SyntaxNode, }; use crate::{ @@ -52,48 +52,27 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - // FIXME: this doesn't try to handle nested declarations - for container in src.value.syntax().ancestors() { - let res = match_ast! { - match container { - ast::TraitDef(it) => { - let c = Trait::from_source(db, src.with_value(it))?; - c.items(db) - .into_iter() - .filter_map(|it| match it { - AssocItem::Function(it) => Some(it), - _ => None - }) - .find(|it| same_source(&it.source(db), &src))? - }, - ast::ImplBlock(it) => { - let c = ImplBlock::from_source(db, src.with_value(it))?; - c.items(db) - .into_iter() - .filter_map(|it| match it { - AssocItem::Function(it) => Some(it), - _ => None - }) - .find(|it| same_source(&it.source(db), &src))? - - }, - _ => { continue }, - } - }; - return Some(res); - } - - let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let c = Module::from_definition(db, src.with_value(module_source))?; - let res = c - .declarations(db) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::Function(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items .into_iter() .filter_map(|it| match it { - ModuleDef::Function(it) => Some(it), + AssocItem::Function(it) => Some(it), _ => None, }) - .find(|it| same_source(&it.source(db), &src)); - res + .find(|it| same_source(&it.source(db), &src)) } } @@ -114,8 +93,27 @@ impl FromSource for Static { impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let id = from_source(db, src)?; - Some(TypeAlias { id }) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::TypeAlias(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items + .into_iter() + .filter_map(|it| match it { + AssocItem::TypeAlias(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) } } @@ -258,6 +256,38 @@ where Some(DEF::from_ast(ctx, &src.value)) } +enum Container { + Trait(Trait), + ImplBlock(ImplBlock), + Module(Module), +} + +impl Container { + fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option { + // FIXME: this doesn't try to handle nested declarations + for container in src.value.ancestors() { + let res = match_ast! { + match container { + ast::TraitDef(it) => { + let c = Trait::from_source(db, src.with_value(it))?; + Container::Trait(c) + }, + ast::ImplBlock(it) => { + let c = ImplBlock::from_source(db, src.with_value(it))?; + Container::ImplBlock(c) + }, + _ => { continue }, + } + }; + return Some(res); + } + + let module_source = ModuleSource::from_child_node(db, src); + let c = Module::from_definition(db, src.with_value(module_source))?; + Some(Container::Module(c)) + } +} + /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// equal if they point to exactly the same object. /// -- cgit v1.2.3 From ee95a35664e6fe9153f6324cfc57872ca365887c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 17:49:57 +0300 Subject: Don't duplicate ContainerId type --- crates/ra_hir/src/code_model.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index b8d48a500..669666989 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,8 +12,8 @@ use hir_def::{ builtin_type::BuiltinType, traits::TraitData, type_ref::{Mutability, TypeRef}, - AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId, - LocalStructFieldId, Lookup, ModuleId, TypeAliasContainerId, UnionId, + AssocItemId, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, + LocalStructFieldId, Lookup, ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -697,9 +697,9 @@ impl Function { pub fn container(self, db: &impl DefDatabase) -> Option { match self.id.lookup(db).container { - FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())), - FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - FunctionContainerId::ModuleId(_) => None, + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } @@ -979,9 +979,9 @@ impl TypeAlias { pub fn container(self, db: &impl DefDatabase) -> Option { match self.id.lookup(db).container { - TypeAliasContainerId::TraitId(it) => Some(Container::Trait(it.into())), - TypeAliasContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - TypeAliasContainerId::ModuleId(_) => None, + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } -- cgit v1.2.3 From 111891dc2dc1d2c7ea87144e8e3ddefe23fc7b6d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 18:00:01 +0300 Subject: Move constants to new ID This allows us to get rid of trait item index --- crates/ra_hir/src/code_model.rs | 25 +++++++++++++++---------- crates/ra_hir/src/code_model/src.rs | 2 +- crates/ra_hir/src/db.rs | 1 - crates/ra_hir/src/from_source.rs | 25 ++++++++++++++++++++++--- crates/ra_hir/src/impl_block.rs | 8 -------- crates/ra_hir/src/source_binder.rs | 7 ++++++- crates/ra_hir/src/ty.rs | 5 +++-- crates/ra_hir/src/ty/tests.rs | 7 +++++-- 8 files changed, 52 insertions(+), 28 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 669666989..920899dce 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -729,7 +729,7 @@ pub struct Const { impl Const { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -748,22 +748,27 @@ impl Const { db.infer(self.into()) } - /// The containing impl block, if this is a method. + /// The containing impl block, if this is a type alias. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - ImplBlock::containing(db, self.into()) + match self.container(db) { + Some(Container::ImplBlock(it)) => Some(it), + _ => None, + } } + /// The containing trait, if this is a trait type alias definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) + match self.container(db) { + Some(Container::Trait(it)) => Some(it), + _ => None, + } } pub fn container(self, db: &impl DefDatabase) -> Option { - if let Some(impl_block) = self.impl_block(db) { - Some(impl_block.into()) - } else if let Some(trait_) = self.parent_trait(db) { - Some(trait_.into()) - } else { - None + match self.id.lookup(db).container { + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 04675e08e..354d2c98f 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -120,7 +120,7 @@ impl HasSource for Function { impl HasSource for Const { type Ast = ast::ConstDef; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Static { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 73859e1e9..5bb7961b3 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -26,7 +26,6 @@ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery, - TraitItemsIndexQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index f5fdaafa3..b86307c58 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -79,8 +79,27 @@ impl FromSource for Function { impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let id = from_source(db, src)?; - Some(Const { id }) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::Const(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items + .into_iter() + .filter_map(|it| match it { + AssocItem::Const(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) } } impl FromSource for Static { @@ -292,7 +311,7 @@ impl Container { /// equal if they point to exactly the same object. /// /// In general, we do not guarantee that we have exactly one instance of a -/// syntax tree for each file. We probably should add such guanratree, but, for +/// syntax tree for each file. We probably should add such guarantee, but, for /// the time being, we will use identity-less AstPtr comparison. fn same_source(s1: &Source, s2: &Source) -> bool { s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 0c2bb8fee..0513f28a9 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -19,14 +19,6 @@ impl HasSource for ImplBlock { } impl ImplBlock { - pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option { - let module = item.module(db); - let crate_def_map = db.crate_def_map(module.id.krate); - crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| { - db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item) - }) - } - pub fn target_trait(&self, db: &impl DefDatabase) -> Option { db.impl_data(self.id).target_trait().cloned() } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index caa8d0082..fd9994098 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -71,7 +71,7 @@ fn def_with_body_from_child_node( match_ast! { match node { ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, + ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, _ => { None }, } @@ -428,6 +428,11 @@ impl SourceAnalyzer { pub(crate) fn inference_result(&self) -> Arc { self.infer.clone().unwrap() } + + #[cfg(test)] + pub(crate) fn analyzed_declaration(&self) -> Option { + self.body_owner + } } fn scope_for( diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 776613c7c..36ece723f 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -3,8 +3,6 @@ mod autoderef; pub(crate) mod primitive; -#[cfg(test)] -mod tests; pub(crate) mod traits; pub(crate) mod method_resolution; mod op; @@ -12,6 +10,9 @@ mod lower; mod infer; pub(crate) mod display; +#[cfg(test)] +mod tests; + use std::ops::Deref; use std::sync::Arc; use std::{fmt, iter, mem}; diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index abfaffb5e..74c12a0a2 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -11,6 +11,7 @@ use ra_syntax::{ ast::{self, AstNode}, SyntaxKind::*, }; +use rustc_hash::FxHashSet; use test_utils::covers; use crate::{ @@ -2518,7 +2519,6 @@ fn test() { [167; 179) 'GLOBAL_CONST': u32 [189; 191) 'id': u32 [194; 210) 'Foo::A..._CONST': u32 - [126; 128) '99': u32 "### ); } @@ -4742,10 +4742,13 @@ fn infer(content: &str) -> String { } }; + let mut analyzed = FxHashSet::default(); for node in source_file.syntax().descendants() { if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None); - infer_def(analyzer.inference_result(), analyzer.body_source_map()); + if analyzed.insert(analyzer.analyzed_declaration()) { + infer_def(analyzer.inference_result(), analyzer.body_source_map()); + } } } -- cgit v1.2.3