diff options
author | Aleksey Kladov <[email protected]> | 2019-01-25 07:15:10 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-25 07:15:10 +0000 |
commit | e884ab05c216fc4a4a35d6267d08519dc5dda41d (patch) | |
tree | b947b2b74afb3950eaef87f85ee0107eb4847f8f /crates/ra_hir | |
parent | 857c35ddb03ee5db97bbb4743dfeedeb3df350ec (diff) |
write path resolution code only once
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 13 |
2 files changed, 14 insertions, 62 deletions
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 6419d3934..a5b190384 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ast, SyntaxNode, TreeArc}; | |||
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | Module, ModuleSource, Problem, ModuleDef, | 5 | Module, ModuleSource, Problem, ModuleDef, |
6 | Crate, Name, Path, PathKind, PerNs, | 6 | Crate, Name, Path, PerNs, |
7 | module_tree::ModuleId, | 7 | module_tree::ModuleId, |
8 | nameres::{ModuleScope, lower::ImportId}, | 8 | nameres::{ModuleScope, lower::ImportId}, |
9 | db::HirDatabase, | 9 | db::HirDatabase, |
@@ -97,65 +97,8 @@ impl Module { | |||
97 | } | 97 | } |
98 | 98 | ||
99 | pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> { | 99 | pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> { |
100 | let mut curr_per_ns: PerNs<ModuleDef> = PerNs::types(match path.kind { | 100 | let item_map = db.item_map(self.krate); |
101 | PathKind::Crate => self.crate_root(db).into(), | 101 | item_map.resolve_path(db, *self, path) |
102 | PathKind::Self_ | PathKind::Plain => self.clone().into(), | ||
103 | PathKind::Super => { | ||
104 | if let Some(p) = self.parent(db) { | ||
105 | p.into() | ||
106 | } else { | ||
107 | return PerNs::none(); | ||
108 | } | ||
109 | } | ||
110 | PathKind::Abs => { | ||
111 | // TODO: absolute use is not supported | ||
112 | return PerNs::none(); | ||
113 | } | ||
114 | }); | ||
115 | |||
116 | for segment in path.segments.iter() { | ||
117 | let curr = match curr_per_ns.as_ref().take_types() { | ||
118 | Some(r) => r, | ||
119 | None => { | ||
120 | // we still have path segments left, but the path so far | ||
121 | // didn't resolve in the types namespace => no resolution | ||
122 | // (don't break here because curr_per_ns might contain | ||
123 | // something in the value namespace, and it would be wrong | ||
124 | // to return that) | ||
125 | return PerNs::none(); | ||
126 | } | ||
127 | }; | ||
128 | // resolve segment in curr | ||
129 | |||
130 | curr_per_ns = match curr { | ||
131 | ModuleDef::Module(m) => { | ||
132 | let scope = m.scope(db); | ||
133 | match scope.get(&segment.name) { | ||
134 | Some(r) => r.def_id.clone(), | ||
135 | None => PerNs::none(), | ||
136 | } | ||
137 | } | ||
138 | ModuleDef::Enum(e) => { | ||
139 | // enum variant | ||
140 | let matching_variant = e | ||
141 | .variants(db) | ||
142 | .into_iter() | ||
143 | .find(|(n, _variant)| n == &segment.name); | ||
144 | |||
145 | match matching_variant { | ||
146 | Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()), | ||
147 | None => PerNs::none(), | ||
148 | } | ||
149 | } | ||
150 | _ => { | ||
151 | // could be an inherent method call in UFCS form | ||
152 | // (`Struct::method`), or some other kind of associated | ||
153 | // item... Which we currently don't handle (TODO) | ||
154 | PerNs::none() | ||
155 | } | ||
156 | }; | ||
157 | } | ||
158 | curr_per_ns | ||
159 | } | 102 | } |
160 | 103 | ||
161 | pub(crate) fn problems_impl( | 104 | pub(crate) fn problems_impl( |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 8c8494b46..0046dfebf 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -297,7 +297,7 @@ where | |||
297 | }; | 297 | }; |
298 | let (def_id, reached_fixedpoint) = | 298 | let (def_id, reached_fixedpoint) = |
299 | self.result | 299 | self.result |
300 | .resolve_path(self.db, original_module, &import.path); | 300 | .resolve_path_fp(self.db, original_module, &import.path); |
301 | 301 | ||
302 | if reached_fixedpoint == ReachedFixedPoint::Yes { | 302 | if reached_fixedpoint == ReachedFixedPoint::Yes { |
303 | let last_segment = import.path.segments.last().unwrap(); | 303 | let last_segment = import.path.segments.last().unwrap(); |
@@ -331,10 +331,19 @@ enum ReachedFixedPoint { | |||
331 | } | 331 | } |
332 | 332 | ||
333 | impl ItemMap { | 333 | impl ItemMap { |
334 | pub(crate) fn resolve_path( | ||
335 | &self, | ||
336 | db: &impl HirDatabase, | ||
337 | original_module: Module, | ||
338 | path: &Path, | ||
339 | ) -> PerNs<ModuleDef> { | ||
340 | self.resolve_path_fp(db, original_module, path).0 | ||
341 | } | ||
342 | |||
334 | // returns true if we are sure that additions to `ItemMap` wouldn't change | 343 | // returns true if we are sure that additions to `ItemMap` wouldn't change |
335 | // the result. That is, if we've reached fixed point at this particular | 344 | // the result. That is, if we've reached fixed point at this particular |
336 | // import. | 345 | // import. |
337 | fn resolve_path( | 346 | fn resolve_path_fp( |
338 | &self, | 347 | &self, |
339 | db: &impl HirDatabase, | 348 | db: &impl HirDatabase, |
340 | original_module: Module, | 349 | original_module: Module, |