aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/module
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r--crates/ra_hir/src/module/imp.rs2
-rw-r--r--crates/ra_hir/src/module/mod.rs31
-rw-r--r--crates/ra_hir/src/module/nameres.rs134
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)]
21pub(crate) enum Submodule { 21pub 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
21pub(crate) use self::nameres::ModuleScope; 21pub 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)]
26pub(crate) struct Module { 26pub 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
32impl Module { 33impl 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)]
191pub(crate) struct ModuleTree { 188pub 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)]
217pub(crate) enum ModuleSource { 214pub 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.
224pub(crate) enum ModuleSourceNode { 221pub enum ModuleSourceNode {
225 SourceFile(ast::SourceFileNode), 222 SourceFile(ast::SourceFileNode),
226 Module(ast::ModuleNode), 223 Module(ast::ModuleNode),
227} 224}
228 225
229pub(crate) type ModuleId = Id<ModuleData>; 226pub type ModuleId = Id<ModuleData>;
230type LinkId = Id<LinkData>; 227type 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)]
311pub(crate) struct ModuleData { 308pub 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)]
41pub(crate) struct ItemMap { 41pub 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)]
46pub(crate) struct ModuleScope { 46pub struct ModuleScope {
47 items: FxHashMap<SmolStr, Resolution>, 47 pub items: FxHashMap<SmolStr, Resolution>,
48} 48}
49 49
50impl ModuleScope { 50impl 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)]
66pub(crate) struct InputModuleItems { 66pub 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)]
92pub(crate) struct NamedImport { 92pub 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
97impl NamedImport { 97impl 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)]
118pub(crate) struct Resolution { 118pub 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)]
341mod 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}