aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-11-20 21:31:12 +0000
committerAleksey Kladov <[email protected]>2018-11-20 21:31:12 +0000
commit9bb11aee44f377fdf2ce7bed5c09ccbcf30f9b57 (patch)
tree881bfa5cf8479690ed3c127b8a27457885a00736 /crates/ra_analysis/src/descriptors
parentaab71bff8eb89fb65f4aba8e90df2ae586ecb0a6 (diff)
populate resolve from unresolved imports
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs13
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs100
2 files changed, 97 insertions, 16 deletions
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index f49e7f909..2d0bfa64c 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -103,9 +103,11 @@ impl ModuleDescriptor {
103 103
104 /// The root of the tree this module is part of 104 /// The root of the tree this module is part of
105 pub fn crate_root(&self) -> ModuleDescriptor { 105 pub fn crate_root(&self) -> ModuleDescriptor {
106 generate(Some(self.clone()), |it| it.parent()) 106 let root_id = self.module_id.crate_root(&self.tree);
107 .last() 107 ModuleDescriptor {
108 .unwrap() 108 module_id: root_id,
109 ..self.clone()
110 }
109 } 111 }
110 112
111 /// `name` is `None` for the crate's root module 113 /// `name` is `None` for the crate's root module
@@ -205,6 +207,11 @@ impl ModuleId {
205 let link = self.parent_link(tree)?; 207 let link = self.parent_link(tree)?;
206 Some(tree.link(link).owner) 208 Some(tree.link(link).owner)
207 } 209 }
210 fn crate_root(self, tree: &ModuleTree) -> ModuleId {
211 generate(Some(self), move |it| it.parent(tree))
212 .last()
213 .unwrap()
214 }
208 fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> { 215 fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
209 let link = tree 216 let link = tree
210 .module(self) 217 .module(self)
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs
index 44059e5c3..058e64ad1 100644
--- a/crates/ra_analysis/src/descriptors/module/nameres.rs
+++ b/crates/ra_analysis/src/descriptors/module/nameres.rs
@@ -52,10 +52,18 @@ struct ItemMap {
52 52
53#[derive(Debug, Default)] 53#[derive(Debug, Default)]
54struct ModuleItems { 54struct ModuleItems {
55 items: FxHashMap<SmolStr, DefId>, 55 items: FxHashMap<SmolStr, Resolution>,
56 import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>, 56 import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
57} 57}
58 58
59/// Resolution is basically `DefId` atm, but it should account for stuff like
60/// multiple namespaces, ambiguity and errors.
61#[derive(Debug, Clone)]
62struct Resolution {
63 /// None for unresolved
64 def_id: Option<DefId>,
65}
66
59#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 67#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
60enum Namespace { 68enum Namespace {
61 Types, 69 Types,
@@ -221,22 +229,27 @@ where
221{ 229{
222 fn resolve(&mut self) { 230 fn resolve(&mut self) {
223 for (&module_id, items) in self.input.iter() { 231 for (&module_id, items) in self.input.iter() {
224 self.populate_module( 232 self.populate_module(module_id, items)
225 module_id, 233 }
226 items, 234
227 ) 235 for &module_id in self.input.keys() {
236 self.resolve_imports(module_id);
228 } 237 }
229 } 238 }
230 239
231 fn populate_module( 240 fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
232 &mut self,
233 module_id: ModuleId,
234 input: &InputModuleItems,
235 ) {
236 let file_id = module_id.source(&self.module_tree).file_id(); 241 let file_id = module_id.source(&self.module_tree).file_id();
237 242
238 let mut module_items = ModuleItems::default(); 243 let mut module_items = ModuleItems::default();
239 244
245 for import in input.imports.iter() {
246 if let Some((_, name)) = import.segments.last() {
247 module_items
248 .items
249 .insert(name.clone(), Resolution { def_id: None });
250 }
251 }
252
240 for item in input.items.iter() { 253 for item in input.items.iter() {
241 if item.kind == MODULE { 254 if item.kind == MODULE {
242 // handle submodules separatelly 255 // handle submodules separatelly
@@ -245,7 +258,10 @@ where
245 let ptr = item.ptr.into_global(file_id); 258 let ptr = item.ptr.into_global(file_id);
246 let def_loc = DefLoc::Item { ptr }; 259 let def_loc = DefLoc::Item { ptr };
247 let def_id = self.db.id_maps().def_id(def_loc); 260 let def_id = self.db.id_maps().def_id(def_loc);
248 module_items.items.insert(item.name.clone(), def_id); 261 let resolution = Resolution {
262 def_id: Some(def_id),
263 };
264 module_items.items.insert(item.name.clone(), resolution);
249 } 265 }
250 266
251 for (name, mod_id) in module_id.children(&self.module_tree) { 267 for (name, mod_id) in module_id.children(&self.module_tree) {
@@ -254,11 +270,69 @@ where
254 source_root: self.source_root, 270 source_root: self.source_root,
255 }; 271 };
256 let def_id = self.db.id_maps().def_id(def_loc); 272 let def_id = self.db.id_maps().def_id(def_loc);
257 module_items.items.insert(name, def_id); 273 let resolution = Resolution {
274 def_id: Some(def_id),
275 };
276 module_items.items.insert(name, resolution);
258 } 277 }
259 278
260 self.result.per_module.insert(module_id, module_items); 279 self.result.per_module.insert(module_id, module_items);
261 } 280 }
262}
263 281
282 fn resolve_imports(&mut self, module_id: ModuleId) {
283 for import in self.input[&module_id].imports.iter() {
284 self.resolve_import(module_id, import);
285 }
286 }
287
288 fn resolve_import(&mut self, module_id: ModuleId, import: &Path) {
289 let mut curr = match import.kind {
290 // TODO: handle extern crates
291 PathKind::Abs => return,
292 PathKind::Self_ => module_id,
293 PathKind::Super => {
294 match module_id.parent(&self.module_tree) {
295 Some(it) => it,
296 // TODO: error
297 None => return,
298 }
299 }
300 PathKind::Crate => module_id.crate_root(&self.module_tree),
301 };
302
303 for (i, (ptr, name)) in import.segments.iter().enumerate() {
304 let is_last = i == import.segments.len() - 1;
305
306 let def_id = match self.result.per_module[&curr].items.get(name) {
307 None => return,
308 Some(res) => match res.def_id {
309 Some(it) => it,
310 None => return,
311 },
312 };
313
314 self.update(module_id, |items| {
315 items.import_resolutions.insert(*ptr, def_id);
316 });
264 317
318 if !is_last {
319 curr = match self.db.id_maps().def_loc(def_id) {
320 DefLoc::Module { id, .. } => id,
321 _ => return,
322 }
323 } else {
324 self.update(module_id, |items| {
325 let res = Resolution {
326 def_id: Some(def_id),
327 };
328 items.items.insert(name.clone(), res);
329 })
330 }
331 }
332 }
333
334 fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) {
335 let module_items = self.result.per_module.get_mut(&module_id).unwrap();
336 f(module_items)
337 }
338}