diff options
Diffstat (limited to 'crates/ra_hir/src/module_tree.rs')
-rw-r--r-- | crates/ra_hir/src/module_tree.rs | 99 |
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::{ | |||
11 | use ra_arena::{Arena, RawId, impl_arena_id}; | 11 | use ra_arena::{Arena, RawId, impl_arena_id}; |
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource}; | 14 | use crate::{ |
15 | Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, | ||
16 | ids::SourceFileItemId, | ||
17 | }; | ||
15 | 18 | ||
16 | impl ModuleSource { | 19 | impl 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 { | |||
34 | pub struct Submodule { | 41 | pub 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 | ||
40 | impl Submodule { | 47 | impl 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)] |
112 | pub struct ModuleData { | 117 | pub 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 | ||
218 | impl ModuleId { | 226 | impl 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 |