From 247d1c17b385ff8a8c1dda2e899495146b643b98 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Fri, 22 Feb 2019 10:15:23 +0200 Subject: Change resolve_path to return the fully resolved path or PerNs::none This also adds new pub(crate) resolve_path_segments which returns the PathResult, which may or may not be fully resolved. PathResult is also now pub(crate) since it is an implementation detail. --- crates/ra_hir/src/impl_block.rs | 2 +- crates/ra_hir/src/resolve.rs | 29 +++++++++-------- crates/ra_hir/src/ty.rs | 39 +++++++++++------------ crates/ra_ide_api/src/completion/complete_path.rs | 2 +- crates/ra_ide_api/src/goto_definition.rs | 2 +- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index f4dccf165..7ecf8c368 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -88,7 +88,7 @@ impl ImplBlock { if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) { let resolver = self.resolver(db); if let Some(Resolution::Def(ModuleDef::Trait(tr))) = - resolver.resolve_path(db, &path).into_per_ns().take_types() + resolver.resolve_path(db, &path).take_types() { return Some(tr); } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 9f4d4ab42..57e7d0b9a 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -33,7 +33,7 @@ pub(crate) struct ExprScope { } #[derive(Debug, Clone)] -pub struct PathResult { +pub(crate) struct PathResult { /// The actual path resolution resolution: PerNs, /// The first index in the path that we @@ -45,7 +45,7 @@ pub struct PathResult { impl PathResult { /// Returns the remaining index in the result /// returns None if the path was fully resolved - pub fn remaining_index(&self) -> Option { + pub(crate) fn remaining_index(&self) -> Option { if self.remaining_index > 0 { Some(self.remaining_index) } else { @@ -55,8 +55,8 @@ impl PathResult { /// Consumes `PathResult` and returns the contained `PerNs` /// if the path was fully resolved, meaning we have no remaining items - pub fn into_per_ns(self) -> PerNs { - if self.remaining_index().is_none() { + pub(crate) fn into_fully_resolved(self) -> PerNs { + if self.is_fully_resolved() { self.resolution } else { PerNs::none() @@ -65,23 +65,17 @@ impl PathResult { /// Consumes `PathResult` and returns the resolution and the /// remaining_index as a tuple. - pub fn into_inner(self) -> (PerNs, Option) { + pub(crate) fn into_inner(self) -> (PerNs, Option) { let index = self.remaining_index(); (self.resolution, index) } /// Path is fully resolved when `remaining_index` is none /// and the resolution contains anything - pub fn is_fully_resolved(&self) -> bool { + pub(crate) fn is_fully_resolved(&self) -> bool { !self.resolution.is_none() && self.remaining_index().is_none() } - /// Empty path result is where the resolution is `none` - /// and the remaining index is 0 - pub fn is_empty(&self) -> bool { - self.resolution.is_none() && self.remaining_index().is_none() - } - fn empty() -> PathResult { PathResult { resolution: PerNs::none(), remaining_index: 0 } } @@ -134,7 +128,9 @@ impl Resolver { resolution } - pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult { + /// Returns the resolved path segments + /// Which may be fully resolved, empty or partially resolved. + pub(crate) fn resolve_path_segments(&self, db: &impl HirDatabase, path: &Path) -> PathResult { if let Some(name) = path.as_ident() { PathResult::from_resolution(self.resolve_name(db, name)) } else if path.is_self() { @@ -156,6 +152,13 @@ impl Resolver { } } + /// Returns the fully resolved path if we were able to resolve it. + /// otherwise returns `PerNs::none` + pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise + self.resolve_path_segments(db, path).into_fully_resolved() + } + pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { let mut names = FxHashMap::default(); for scope in self.scopes.iter().rev() { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b1f35ab1f..89e854dd7 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -370,7 +370,7 @@ impl Ty { } // Resolve the path (in type namespace) - let resolution = resolver.resolve_path(db, path).into_per_ns().take_types(); + let resolution = resolver.resolve_path(db, path).take_types(); let def = match resolution { Some(Resolution::Def(def)) => def, @@ -1172,7 +1172,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option { - let resolved = resolver.resolve_path(self.db, &path); + let resolved = resolver.resolve_path_segments(self.db, &path); let (def, remaining_index) = resolved.into_inner(); @@ -1244,24 +1244,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { None => return (Ty::Unknown, None), }; let resolver = &self.resolver; - let typable: Option = - match resolver.resolve_path(self.db, &path).into_per_ns().take_types() { - Some(Resolution::Def(def)) => def.into(), - Some(Resolution::LocalBinding(..)) => { - // this cannot happen - log::error!("path resolved to local binding in type ns"); - return (Ty::Unknown, None); - } - Some(Resolution::GenericParam(..)) => { - // generic params can't be used in struct literals - return (Ty::Unknown, None); - } - Some(Resolution::SelfType(..)) => { - // TODO this is allowed in an impl for a struct, handle this - return (Ty::Unknown, None); - } - None => return (Ty::Unknown, None), - }; + let typable: Option = match resolver.resolve_path(self.db, &path).take_types() { + Some(Resolution::Def(def)) => def.into(), + Some(Resolution::LocalBinding(..)) => { + // this cannot happen + log::error!("path resolved to local binding in type ns"); + return (Ty::Unknown, None); + } + Some(Resolution::GenericParam(..)) => { + // generic params can't be used in struct literals + return (Ty::Unknown, None); + } + Some(Resolution::SelfType(..)) => { + // TODO this is allowed in an impl for a struct, handle this + return (Ty::Unknown, None); + } + None => return (Ty::Unknown, None), + }; let def = match typable { None => return (Ty::Unknown, None), Some(it) => it, diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index a0c5572d5..d337fe970 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -10,7 +10,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { Some(path) => path.clone(), _ => return, }; - let def = match ctx.resolver.resolve_path(ctx.db, &path).into_per_ns().take_types() { + let def = match ctx.resolver.resolve_path(ctx.db, &path).take_types() { Some(Resolution::Def(def)) => def, _ => return, }; diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 76aaebd52..96ed8c8e9 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -79,7 +79,7 @@ pub(crate) fn reference_definition( if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast).and_then(hir::Path::from_ast) { - let resolved = resolver.resolve_path(db, &path).into_per_ns(); + let resolved = resolver.resolve_path(db, &path); match resolved.clone().take_types().or_else(|| resolved.take_values()) { Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)), Some(Resolution::LocalBinding(pat)) => { -- cgit v1.2.3