From 4497e1d3eae0a72ee1e52be6ab547c67d31279c6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 14 Apr 2019 11:15:11 +0200 Subject: Add Container enum to handle both kinds of container (impl/trait) --- crates/ra_hir/src/code_model_api.rs | 51 +++++++++++++++++++++++++++++++------ crates/ra_hir/src/generics.rs | 20 ++++++++++----- crates/ra_hir/src/impl_block.rs | 2 +- crates/ra_hir/src/lib.rs | 2 +- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index b53fe1f63..28de9e76a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -189,7 +189,7 @@ impl Module { } } - pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let def_map = db.crate_def_map(self.krate); Resolver::default().push_module_scope(def_map, self.module_id) } @@ -552,16 +552,21 @@ impl Function { db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) } + 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 + } + } + // FIXME: move to a more general type for 'body-having' items /// Builds a resolver for code inside this item. pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... - // FIXME abstract over containers (trait/impl) - let r = self - .impl_block(db) - .map(|ib| ib.resolver(db)) - .or_else(|| self.parent_trait(db).map(|tr| tr.resolver(db))) - .unwrap_or_else(|| self.module(db).resolver(db)); + let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db)); // ...and add generic params, if present let p = self.generic_params(db); let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; @@ -707,7 +712,7 @@ impl Trait { db.trait_data(self) } - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let r = self.module(db).resolver(db); // add generic params, if present let p = self.generic_params(db); @@ -746,6 +751,21 @@ impl TypeAlias { ImplBlock::containing(module_impls, (*self).into()) } + /// The containing trait, if this is a trait method definition. + pub fn parent_trait(&self, db: &impl DefDatabase) -> Option { + db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) + } + + 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 + } + } + pub fn type_ref(self, db: &impl DefDatabase) -> Arc { db.type_alias_ref(self) } @@ -769,3 +789,18 @@ impl Docs for TypeAlias { docs_from_ast(&*self.source(db).1) } } + +pub enum Container { + Trait(Trait), + ImplBlock(ImplBlock), +} +impl_froms!(Container: Trait, ImplBlock); + +impl Container { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { + match self { + Container::Trait(trait_) => trait_.resolver(db), + Container::ImplBlock(impl_block) => impl_block.resolver(db), + } + } +} diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 51c846e91..f92b146ef 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; use crate::{ db::DefDatabase, - Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock + Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -27,6 +27,7 @@ pub struct GenericParams { pub(crate) params: Vec, } +// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum GenericDef { Function(Function), @@ -45,12 +46,8 @@ impl GenericParams { ) -> Arc { let mut generics = GenericParams::default(); let parent = match def { - // FIXME abstract over containers (trait/impl) - GenericDef::Function(it) => it - .impl_block(db) - .map(GenericDef::from) - .or_else(|| it.parent_trait(db).map(GenericDef::from)), - GenericDef::TypeAlias(it) => it.impl_block(db).map(GenericDef::from), + GenericDef::Function(it) => it.container(db).map(GenericDef::from), + GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, GenericDef::ImplBlock(_) => None, }; @@ -112,3 +109,12 @@ impl GenericParams { vec } } + +impl From for GenericDef { + fn from(c: Container) -> Self { + match c { + Container::Trait(trait_) => trait_.into(), + Container::ImplBlock(impl_block) => impl_block.into(), + } + } +} diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 42c02c9fb..71486aa2d 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -96,7 +96,7 @@ impl ImplBlock { db.generic_params((*self).into()) } - pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let r = self.module().resolver(db); // add generic params, if present let p = self.generic_params(db); diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index c284d1693..24e08f8cc 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -78,5 +78,5 @@ pub use self::code_model_api::{ Function, FnSignature, StructField, FieldSource, Static, Const, ConstSignature, - Trait, TypeAlias, + Trait, TypeAlias, Container, }; -- cgit v1.2.3