aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/module_tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/module_tree.rs')
-rw-r--r--crates/ra_hir/src/module_tree.rs99
1 files changed, 55 insertions, 44 deletions
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index d5ad9decb..d1dc3fa4b 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -11,21 +11,28 @@ use ra_syntax::{
11use ra_arena::{Arena, RawId, impl_arena_id}; 11use ra_arena::{Arena, RawId, impl_arena_id};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource}; 14use crate::{
15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource,
16 ids::SourceFileItemId,
17};
15 18
16impl ModuleSource { 19impl ModuleSource {
17 pub(crate) fn from_source_item_id( 20 pub(crate) fn new(
18 db: &impl HirDatabase, 21 db: &impl HirDatabase,
19 source_item_id: SourceItemId, 22 file_id: HirFileId,
23 decl_id: Option<SourceFileItemId>,
20 ) -> ModuleSource { 24 ) -> ModuleSource {
21 let module_syntax = db.file_item(source_item_id); 25 match decl_id {
22 if let Some(source_file) = ast::SourceFile::cast(&module_syntax) { 26 Some(item_id) => {
23 ModuleSource::SourceFile(source_file.to_owned()) 27 let module = db.file_item(SourceItemId { file_id, item_id });
24 } else if let Some(module) = ast::Module::cast(&module_syntax) { 28 let module = ast::Module::cast(&*module).unwrap();
25 assert!(module.item_list().is_some(), "expected inline module"); 29 assert!(module.item_list().is_some(), "expected inline module");
26 ModuleSource::Module(module.to_owned()) 30 ModuleSource::Module(module.to_owned())
27 } else { 31 }
28 panic!("expected file or inline module") 32 None => {
33 let source_file = db.hir_parse(file_id);
34 ModuleSource::SourceFile(source_file)
35 }
29 } 36 }
30 } 37 }
31} 38}
@@ -34,18 +41,18 @@ impl ModuleSource {
34pub struct Submodule { 41pub struct Submodule {
35 name: Name, 42 name: Name,
36 is_declaration: bool, 43 is_declaration: bool,
37 source: SourceItemId, 44 decl_id: SourceFileItemId,
38} 45}
39 46
40impl Submodule { 47impl Submodule {
41 pub(crate) fn submodules_query( 48 pub(crate) fn submodules_query(
42 db: &impl HirDatabase, 49 db: &impl HirDatabase,
43 source: SourceItemId, 50 file_id: HirFileId,
51 decl_id: Option<SourceFileItemId>,
44 ) -> Arc<Vec<Submodule>> { 52 ) -> Arc<Vec<Submodule>> {
45 db.check_canceled(); 53 db.check_canceled();
46 let file_id = source.file_id;
47 let file_items = db.file_items(file_id); 54 let file_items = db.file_items(file_id);
48 let module_source = ModuleSource::from_source_item_id(db, source); 55 let module_source = ModuleSource::new(db, file_id, decl_id);
49 let submodules = match module_source { 56 let submodules = match module_source {
50 ModuleSource::SourceFile(source_file) => { 57 ModuleSource::SourceFile(source_file) => {
51 collect_submodules(file_id, &file_items, &*source_file) 58 collect_submodules(file_id, &file_items, &*source_file)
@@ -54,6 +61,7 @@ impl Submodule {
54 collect_submodules(file_id, &file_items, module.item_list().unwrap()) 61 collect_submodules(file_id, &file_items, module.item_list().unwrap())
55 } 62 }
56 }; 63 };
64
57 return Arc::new(submodules); 65 return Arc::new(submodules);
58 66
59 fn collect_submodules( 67 fn collect_submodules(
@@ -75,10 +83,7 @@ impl Submodule {
75 let sub = Submodule { 83 let sub = Submodule {
76 name, 84 name,
77 is_declaration: module.has_semi(), 85 is_declaration: module.has_semi(),
78 source: SourceItemId { 86 decl_id: file_items.id_of(file_id, module.syntax()),
79 file_id,
80 item_id: Some(file_items.id_of(file_id, module.syntax())),
81 },
82 }; 87 };
83 Some(sub) 88 Some(sub)
84 }) 89 })
@@ -110,7 +115,9 @@ pub struct ModuleTree {
110 115
111#[derive(Debug, PartialEq, Eq, Hash)] 116#[derive(Debug, PartialEq, Eq, Hash)]
112pub struct ModuleData { 117pub struct ModuleData {
113 source: SourceItemId, 118 file_id: HirFileId,
119 /// Points to `ast::Module`, `None` for the whole file.
120 decl_id: Option<SourceFileItemId>,
114 parent: Option<LinkId>, 121 parent: Option<LinkId>,
115 children: Vec<LinkId>, 122 children: Vec<LinkId>,
116} 123}
@@ -136,8 +143,15 @@ impl ModuleTree {
136 self.mods.iter().map(|(id, _)| id) 143 self.mods.iter().map(|(id, _)| id)
137 } 144 }
138 145
139 pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> { 146 pub(crate) fn find_module_by_source(
140 let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?; 147 &self,
148 file_id: HirFileId,
149 decl_id: Option<SourceFileItemId>,
150 ) -> Option<ModuleId> {
151 let (res, _) = self
152 .mods
153 .iter()
154 .find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?;
141 Some(res) 155 Some(res)
142 } 156 }
143 157
@@ -147,11 +161,7 @@ impl ModuleTree {
147 let source_root_id = db.file_source_root(file_id); 161 let source_root_id = db.file_source_root(file_id);
148 162
149 let source_root = db.source_root(source_root_id); 163 let source_root = db.source_root(source_root_id);
150 let source = SourceItemId { 164 self.init_subtree(db, &source_root, None, file_id.into(), None);
151 file_id: file_id.into(),
152 item_id: None,
153 };
154 self.init_subtree(db, &source_root, None, source);
155 } 165 }
156 166
157 fn init_subtree( 167 fn init_subtree(
@@ -159,16 +169,21 @@ impl ModuleTree {
159 db: &impl HirDatabase, 169 db: &impl HirDatabase,
160 source_root: &SourceRoot, 170 source_root: &SourceRoot,
161 parent: Option<LinkId>, 171 parent: Option<LinkId>,
162 source: SourceItemId, 172 file_id: HirFileId,
173 decl_id: Option<SourceFileItemId>,
163 ) -> ModuleId { 174 ) -> ModuleId {
164 let id = self.alloc_mod(ModuleData { 175 let id = self.alloc_mod(ModuleData {
165 source, 176 file_id,
177 decl_id,
166 parent, 178 parent,
167 children: Vec::new(), 179 children: Vec::new(),
168 }); 180 });
169 for sub in db.submodules(source).iter() { 181 for sub in db.submodules(file_id, decl_id).iter() {
170 let link = self.alloc_link(LinkData { 182 let link = self.alloc_link(LinkData {
171 source: sub.source, 183 source: SourceItemId {
184 file_id,
185 item_id: sub.decl_id,
186 },
172 name: sub.name.clone(), 187 name: sub.name.clone(),
173 owner: id, 188 owner: id,
174 points_to: Vec::new(), 189 points_to: Vec::new(),
@@ -176,24 +191,17 @@ impl ModuleTree {
176 }); 191 });
177 192
178 let (points_to, problem) = if sub.is_declaration { 193 let (points_to, problem) = if sub.is_declaration {
179 let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name); 194 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name);
180 let points_to = points_to 195 let points_to = points_to
181 .into_iter() 196 .into_iter()
182 .map(|file_id| { 197 .map(|file_id| {
183 self.init_subtree( 198 self.init_subtree(db, source_root, Some(link), file_id.into(), None)
184 db,
185 source_root,
186 Some(link),
187 SourceItemId {
188 file_id: file_id.into(),
189 item_id: None,
190 },
191 )
192 }) 199 })
193 .collect::<Vec<_>>(); 200 .collect::<Vec<_>>();
194 (points_to, problem) 201 (points_to, problem)
195 } else { 202 } else {
196 let points_to = self.init_subtree(db, source_root, Some(link), sub.source); 203 let points_to =
204 self.init_subtree(db, source_root, Some(link), file_id, Some(sub.decl_id));
197 (vec![points_to], None) 205 (vec![points_to], None)
198 }; 206 };
199 207
@@ -216,8 +224,11 @@ impl ModuleTree {
216} 224}
217 225
218impl ModuleId { 226impl ModuleId {
219 pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId { 227 pub(crate) fn file_id(self, tree: &ModuleTree) -> HirFileId {
220 tree.mods[self].source 228 tree.mods[self].file_id
229 }
230 pub(crate) fn decl_id(self, tree: &ModuleTree) -> Option<SourceFileItemId> {
231 tree.mods[self].decl_id
221 } 232 }
222 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { 233 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
223 tree.mods[self].parent 234 tree.mods[self].parent