aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/resolve.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r--crates/ra_hir/src/resolve.rs89
1 files changed, 83 insertions, 6 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 91a531801..57e7d0b9a 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -33,6 +33,67 @@ pub(crate) struct ExprScope {
33} 33}
34 34
35#[derive(Debug, Clone)] 35#[derive(Debug, Clone)]
36pub(crate) struct PathResult {
37 /// The actual path resolution
38 resolution: PerNs<Resolution>,
39 /// The first index in the path that we
40 /// were unable to resolve.
41 /// When path is fully resolved, this is 0.
42 remaining_index: usize,
43}
44
45impl PathResult {
46 /// Returns the remaining index in the result
47 /// returns None if the path was fully resolved
48 pub(crate) fn remaining_index(&self) -> Option<usize> {
49 if self.remaining_index > 0 {
50 Some(self.remaining_index)
51 } else {
52 None
53 }
54 }
55
56 /// Consumes `PathResult` and returns the contained `PerNs<Resolution>`
57 /// if the path was fully resolved, meaning we have no remaining items
58 pub(crate) fn into_fully_resolved(self) -> PerNs<Resolution> {
59 if self.is_fully_resolved() {
60 self.resolution
61 } else {
62 PerNs::none()
63 }
64 }
65
66 /// Consumes `PathResult` and returns the resolution and the
67 /// remaining_index as a tuple.
68 pub(crate) fn into_inner(self) -> (PerNs<Resolution>, Option<usize>) {
69 let index = self.remaining_index();
70 (self.resolution, index)
71 }
72
73 /// Path is fully resolved when `remaining_index` is none
74 /// and the resolution contains anything
75 pub(crate) fn is_fully_resolved(&self) -> bool {
76 !self.resolution.is_none() && self.remaining_index().is_none()
77 }
78
79 fn empty() -> PathResult {
80 PathResult { resolution: PerNs::none(), remaining_index: 0 }
81 }
82
83 fn from_resolution(res: PerNs<Resolution>) -> PathResult {
84 PathResult::from_resolution_with_index(res, 0)
85 }
86
87 fn from_resolution_with_index(res: PerNs<Resolution>, remaining_index: usize) -> PathResult {
88 if res.is_none() {
89 PathResult::empty()
90 } else {
91 PathResult { resolution: res, remaining_index }
92 }
93 }
94}
95
96#[derive(Debug, Clone)]
36pub(crate) enum Scope { 97pub(crate) enum Scope {
37 /// All the items and imported names of a module 98 /// All the items and imported names of a module
38 ModuleScope(ModuleItemMap), 99 ModuleScope(ModuleItemMap),
@@ -67,21 +128,37 @@ impl Resolver {
67 resolution 128 resolution
68 } 129 }
69 130
70 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { 131 /// Returns the resolved path segments
132 /// Which may be fully resolved, empty or partially resolved.
133 pub(crate) fn resolve_path_segments(&self, db: &impl HirDatabase, path: &Path) -> PathResult {
71 if let Some(name) = path.as_ident() { 134 if let Some(name) = path.as_ident() {
72 self.resolve_name(db, name) 135 PathResult::from_resolution(self.resolve_name(db, name))
73 } else if path.is_self() { 136 } else if path.is_self() {
74 self.resolve_name(db, &Name::self_param()) 137 PathResult::from_resolution(self.resolve_name(db, &Name::self_param()))
75 } else { 138 } else {
76 let (item_map, module) = match self.module() { 139 let (item_map, module) = match self.module() {
77 Some(m) => m, 140 Some(m) => m,
78 _ => return PerNs::none(), 141 _ => return PathResult::empty(),
79 }; 142 };
80 let module_res = item_map.resolve_path(db, module, path); 143 let (module_res, segment_index) = item_map.resolve_path(db, module, path);
81 module_res.map(Resolution::Def) 144
145 let def = module_res.map(Resolution::Def);
146
147 if let Some(index) = segment_index {
148 PathResult::from_resolution_with_index(def, index)
149 } else {
150 PathResult::from_resolution(def)
151 }
82 } 152 }
83 } 153 }
84 154
155 /// Returns the fully resolved path if we were able to resolve it.
156 /// otherwise returns `PerNs::none`
157 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> {
158 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise
159 self.resolve_path_segments(db, path).into_fully_resolved()
160 }
161
85 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> { 162 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> {
86 let mut names = FxHashMap::default(); 163 let mut names = FxHashMap::default();
87 for scope in self.scopes.iter().rev() { 164 for scope in self.scopes.iter().rev() {