diff options
Diffstat (limited to 'crates/ra_hir/src/module/nameres.rs')
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 134 |
1 files changed, 14 insertions, 120 deletions
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 513a37646..837a8d5ae 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -38,20 +38,20 @@ use crate::{ | |||
38 | /// Item map is the result of the name resolution. Item map contains, for each | 38 | /// Item map is the result of the name resolution. Item map contains, for each |
39 | /// module, the set of visible items. | 39 | /// module, the set of visible items. |
40 | #[derive(Default, Debug, PartialEq, Eq)] | 40 | #[derive(Default, Debug, PartialEq, Eq)] |
41 | pub(crate) struct ItemMap { | 41 | pub struct ItemMap { |
42 | pub(crate) per_module: FxHashMap<ModuleId, ModuleScope>, | 42 | pub per_module: FxHashMap<ModuleId, ModuleScope>, |
43 | } | 43 | } |
44 | 44 | ||
45 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 45 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
46 | pub(crate) struct ModuleScope { | 46 | pub struct ModuleScope { |
47 | items: FxHashMap<SmolStr, Resolution>, | 47 | pub items: FxHashMap<SmolStr, Resolution>, |
48 | } | 48 | } |
49 | 49 | ||
50 | impl ModuleScope { | 50 | impl ModuleScope { |
51 | pub(crate) fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a { | 51 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a { |
52 | self.items.iter() | 52 | self.items.iter() |
53 | } | 53 | } |
54 | pub(crate) fn get(&self, name: &SmolStr) -> Option<&Resolution> { | 54 | pub fn get(&self, name: &SmolStr) -> Option<&Resolution> { |
55 | self.items.get(name) | 55 | self.items.get(name) |
56 | } | 56 | } |
57 | } | 57 | } |
@@ -63,7 +63,7 @@ impl ModuleScope { | |||
63 | /// recomputing name res: if `InputModuleItems` are the same, we can avoid | 63 | /// recomputing name res: if `InputModuleItems` are the same, we can avoid |
64 | /// running name resolution. | 64 | /// running name resolution. |
65 | #[derive(Debug, Default, PartialEq, Eq)] | 65 | #[derive(Debug, Default, PartialEq, Eq)] |
66 | pub(crate) struct InputModuleItems { | 66 | pub struct InputModuleItems { |
67 | items: Vec<ModuleItem>, | 67 | items: Vec<ModuleItem>, |
68 | imports: Vec<Import>, | 68 | imports: Vec<Import>, |
69 | } | 69 | } |
@@ -89,13 +89,13 @@ struct Import { | |||
89 | } | 89 | } |
90 | 90 | ||
91 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 91 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
92 | pub(crate) struct NamedImport { | 92 | pub struct NamedImport { |
93 | file_item_id: SourceFileItemId, | 93 | pub file_item_id: SourceFileItemId, |
94 | relative_range: TextRange, | 94 | pub relative_range: TextRange, |
95 | } | 95 | } |
96 | 96 | ||
97 | impl NamedImport { | 97 | impl NamedImport { |
98 | pub(crate) fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | 98 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { |
99 | let source_item_id = SourceItemId { | 99 | let source_item_id = SourceItemId { |
100 | file_id, | 100 | file_id, |
101 | item_id: self.file_item_id, | 101 | item_id: self.file_item_id, |
@@ -115,11 +115,11 @@ enum ImportKind { | |||
115 | /// Resolution is basically `DefId` atm, but it should account for stuff like | 115 | /// Resolution is basically `DefId` atm, but it should account for stuff like |
116 | /// multiple namespaces, ambiguity and errors. | 116 | /// multiple namespaces, ambiguity and errors. |
117 | #[derive(Debug, Clone, PartialEq, Eq)] | 117 | #[derive(Debug, Clone, PartialEq, Eq)] |
118 | pub(crate) struct Resolution { | 118 | pub struct Resolution { |
119 | /// None for unresolved | 119 | /// None for unresolved |
120 | pub(crate) def_id: Option<DefId>, | 120 | pub def_id: Option<DefId>, |
121 | /// ident by whitch this is imported into local scope. | 121 | /// ident by whitch this is imported into local scope. |
122 | pub(crate) import: Option<NamedImport>, | 122 | pub import: Option<NamedImport>, |
123 | } | 123 | } |
124 | 124 | ||
125 | // #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 125 | // #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -336,109 +336,3 @@ where | |||
336 | f(module_items) | 336 | f(module_items) |
337 | } | 337 | } |
338 | } | 338 | } |
339 | |||
340 | #[cfg(test)] | ||
341 | mod tests { | ||
342 | use ra_db::FilesDatabase; | ||
343 | use crate::{ | ||
344 | AnalysisChange, | ||
345 | mock_analysis::{MockAnalysis, analysis_and_position}, | ||
346 | hir::{self, HirDatabase}, | ||
347 | }; | ||
348 | use super::*; | ||
349 | |||
350 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | ||
351 | let (analysis, pos) = analysis_and_position(fixture); | ||
352 | let db = analysis.imp.db; | ||
353 | let source_root = db.file_source_root(pos.file_id); | ||
354 | let descr = hir::Module::guess_from_position(&*db, pos) | ||
355 | .unwrap() | ||
356 | .unwrap(); | ||
357 | let module_id = descr.module_id; | ||
358 | (db.item_map(source_root).unwrap(), module_id) | ||
359 | } | ||
360 | |||
361 | #[test] | ||
362 | fn test_item_map() { | ||
363 | let (item_map, module_id) = item_map( | ||
364 | " | ||
365 | //- /lib.rs | ||
366 | mod foo; | ||
367 | |||
368 | use crate::foo::bar::Baz; | ||
369 | <|> | ||
370 | |||
371 | //- /foo/mod.rs | ||
372 | pub mod bar; | ||
373 | |||
374 | //- /foo/bar.rs | ||
375 | pub struct Baz; | ||
376 | ", | ||
377 | ); | ||
378 | let name = SmolStr::from("Baz"); | ||
379 | let resolution = &item_map.per_module[&module_id].items[&name]; | ||
380 | assert!(resolution.def_id.is_some()); | ||
381 | } | ||
382 | |||
383 | #[test] | ||
384 | fn typing_inside_a_function_should_not_invalidate_item_map() { | ||
385 | let mock_analysis = MockAnalysis::with_files( | ||
386 | " | ||
387 | //- /lib.rs | ||
388 | mod foo; | ||
389 | |||
390 | use crate::foo::bar::Baz; | ||
391 | |||
392 | fn foo() -> i32 { | ||
393 | 1 + 1 | ||
394 | } | ||
395 | //- /foo/mod.rs | ||
396 | pub mod bar; | ||
397 | |||
398 | //- /foo/bar.rs | ||
399 | pub struct Baz; | ||
400 | ", | ||
401 | ); | ||
402 | |||
403 | let file_id = mock_analysis.id_of("/lib.rs"); | ||
404 | let mut host = mock_analysis.analysis_host(); | ||
405 | |||
406 | let source_root = host.analysis().imp.db.file_source_root(file_id); | ||
407 | |||
408 | { | ||
409 | let db = host.analysis().imp.db; | ||
410 | let events = db.log_executed(|| { | ||
411 | db.item_map(source_root).unwrap(); | ||
412 | }); | ||
413 | assert!(format!("{:?}", events).contains("item_map")) | ||
414 | } | ||
415 | |||
416 | let mut change = AnalysisChange::new(); | ||
417 | |||
418 | change.change_file( | ||
419 | file_id, | ||
420 | " | ||
421 | mod foo; | ||
422 | |||
423 | use crate::foo::bar::Baz; | ||
424 | |||
425 | fn foo() -> i32 { 92 } | ||
426 | " | ||
427 | .to_string(), | ||
428 | ); | ||
429 | |||
430 | host.apply_change(change); | ||
431 | |||
432 | { | ||
433 | let db = host.analysis().imp.db; | ||
434 | let events = db.log_executed(|| { | ||
435 | db.item_map(source_root).unwrap(); | ||
436 | }); | ||
437 | assert!( | ||
438 | !format!("{:?}", events).contains("_item_map"), | ||
439 | "{:#?}", | ||
440 | events | ||
441 | ) | ||
442 | } | ||
443 | } | ||
444 | } | ||