diff options
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/module/mod.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 134 |
3 files changed, 29 insertions, 138 deletions
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index d55fa3e6b..76ea129a7 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs | |||
@@ -18,7 +18,7 @@ use super::{ | |||
18 | }; | 18 | }; |
19 | 19 | ||
20 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | 20 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
21 | pub(crate) enum Submodule { | 21 | pub enum Submodule { |
22 | Declaration(SmolStr), | 22 | Declaration(SmolStr), |
23 | Definition(SmolStr, ModuleSource), | 23 | Definition(SmolStr, ModuleSource), |
24 | } | 24 | } |
diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module/mod.rs index 81b9f948d..a011fd53e 100644 --- a/crates/ra_hir/src/module/mod.rs +++ b/crates/ra_hir/src/module/mod.rs | |||
@@ -18,15 +18,16 @@ use crate::{ | |||
18 | arena::{Arena, Id}, | 18 | arena::{Arena, Id}, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub(crate) use self::nameres::ModuleScope; | 21 | pub use self::nameres::ModuleScope; |
22 | 22 | ||
23 | /// `Module` is API entry point to get all the information | 23 | /// `Module` is API entry point to get all the information |
24 | /// about a particular module. | 24 | /// about a particular module. |
25 | #[derive(Debug, Clone)] | 25 | #[derive(Debug, Clone)] |
26 | pub(crate) struct Module { | 26 | pub struct Module { |
27 | tree: Arc<ModuleTree>, | 27 | tree: Arc<ModuleTree>, |
28 | source_root_id: SourceRootId, | 28 | source_root_id: SourceRootId, |
29 | module_id: ModuleId, | 29 | //TODO: make private |
30 | pub module_id: ModuleId, | ||
30 | } | 31 | } |
31 | 32 | ||
32 | impl Module { | 33 | impl Module { |
@@ -145,17 +146,13 @@ impl Module { | |||
145 | } | 146 | } |
146 | 147 | ||
147 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 148 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
148 | pub(crate) fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | 149 | pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { |
149 | let item_map = db.item_map(self.source_root_id)?; | 150 | let item_map = db.item_map(self.source_root_id)?; |
150 | let res = item_map.per_module[&self.module_id].clone(); | 151 | let res = item_map.per_module[&self.module_id].clone(); |
151 | Ok(res) | 152 | Ok(res) |
152 | } | 153 | } |
153 | 154 | ||
154 | pub(crate) fn resolve_path( | 155 | pub fn resolve_path(&self, db: &impl HirDatabase, path: Path) -> Cancelable<Option<DefId>> { |
155 | &self, | ||
156 | db: &impl HirDatabase, | ||
157 | path: Path, | ||
158 | ) -> Cancelable<Option<DefId>> { | ||
159 | let mut curr = match path.kind { | 156 | let mut curr = match path.kind { |
160 | PathKind::Crate => self.crate_root(), | 157 | PathKind::Crate => self.crate_root(), |
161 | PathKind::Self_ | PathKind::Plain => self.clone(), | 158 | PathKind::Self_ | PathKind::Plain => self.clone(), |
@@ -188,7 +185,7 @@ impl Module { | |||
188 | /// (which can have multiple parents) to the precise world of modules (which | 185 | /// (which can have multiple parents) to the precise world of modules (which |
189 | /// always have one parent). | 186 | /// always have one parent). |
190 | #[derive(Default, Debug, PartialEq, Eq)] | 187 | #[derive(Default, Debug, PartialEq, Eq)] |
191 | pub(crate) struct ModuleTree { | 188 | pub struct ModuleTree { |
192 | mods: Arena<ModuleData>, | 189 | mods: Arena<ModuleData>, |
193 | links: Arena<LinkData>, | 190 | links: Arena<LinkData>, |
194 | } | 191 | } |
@@ -214,19 +211,19 @@ impl ModuleTree { | |||
214 | /// `ModuleSource` is the syntax tree element that produced this module: | 211 | /// `ModuleSource` is the syntax tree element that produced this module: |
215 | /// either a file, or an inlinde module. | 212 | /// either a file, or an inlinde module. |
216 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 213 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
217 | pub(crate) enum ModuleSource { | 214 | pub enum ModuleSource { |
218 | SourceFile(FileId), | 215 | SourceFile(FileId), |
219 | Module(SourceItemId), | 216 | Module(SourceItemId), |
220 | } | 217 | } |
221 | 218 | ||
222 | /// An owned syntax node for a module. Unlike `ModuleSource`, | 219 | /// An owned syntax node for a module. Unlike `ModuleSource`, |
223 | /// this holds onto the AST for the whole file. | 220 | /// this holds onto the AST for the whole file. |
224 | pub(crate) enum ModuleSourceNode { | 221 | pub enum ModuleSourceNode { |
225 | SourceFile(ast::SourceFileNode), | 222 | SourceFile(ast::SourceFileNode), |
226 | Module(ast::ModuleNode), | 223 | Module(ast::ModuleNode), |
227 | } | 224 | } |
228 | 225 | ||
229 | pub(crate) type ModuleId = Id<ModuleData>; | 226 | pub type ModuleId = Id<ModuleData>; |
230 | type LinkId = Id<LinkData>; | 227 | type LinkId = Id<LinkData>; |
231 | 228 | ||
232 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | 229 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
@@ -308,7 +305,7 @@ impl LinkId { | |||
308 | } | 305 | } |
309 | 306 | ||
310 | #[derive(Debug, PartialEq, Eq, Hash)] | 307 | #[derive(Debug, PartialEq, Eq, Hash)] |
311 | pub(crate) struct ModuleData { | 308 | pub struct ModuleData { |
312 | source: ModuleSource, | 309 | source: ModuleSource, |
313 | parent: Option<LinkId>, | 310 | parent: Option<LinkId>, |
314 | children: Vec<LinkId>, | 311 | children: Vec<LinkId>, |
@@ -327,21 +324,21 @@ impl ModuleSource { | |||
327 | ModuleSource::Module(id) | 324 | ModuleSource::Module(id) |
328 | } | 325 | } |
329 | 326 | ||
330 | pub(crate) fn as_file(self) -> Option<FileId> { | 327 | pub fn as_file(self) -> Option<FileId> { |
331 | match self { | 328 | match self { |
332 | ModuleSource::SourceFile(f) => Some(f), | 329 | ModuleSource::SourceFile(f) => Some(f), |
333 | ModuleSource::Module(..) => None, | 330 | ModuleSource::Module(..) => None, |
334 | } | 331 | } |
335 | } | 332 | } |
336 | 333 | ||
337 | pub(crate) fn file_id(self) -> FileId { | 334 | pub fn file_id(self) -> FileId { |
338 | match self { | 335 | match self { |
339 | ModuleSource::SourceFile(f) => f, | 336 | ModuleSource::SourceFile(f) => f, |
340 | ModuleSource::Module(source_item_id) => source_item_id.file_id, | 337 | ModuleSource::Module(source_item_id) => source_item_id.file_id, |
341 | } | 338 | } |
342 | } | 339 | } |
343 | 340 | ||
344 | pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { | 341 | pub fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode { |
345 | match self { | 342 | match self { |
346 | ModuleSource::SourceFile(file_id) => { | 343 | ModuleSource::SourceFile(file_id) => { |
347 | let syntax = db.source_file(file_id); | 344 | let syntax = db.source_file(file_id); |
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 | } | ||