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 +++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'crates/ra_hir/src/code_model_api.rs') 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), + } + } +} -- cgit v1.2.3