diff options
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 85 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres/tests.rs | 84 |
3 files changed, 137 insertions, 38 deletions
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index eded85a63..3849026db 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs | |||
@@ -64,7 +64,7 @@ fn create_module_tree<'a>( | |||
64 | 64 | ||
65 | let source_root = db.source_root(source_root); | 65 | let source_root = db.source_root(source_root); |
66 | for &file_id in source_root.files.values() { | 66 | for &file_id in source_root.files.values() { |
67 | let source = ModuleSource::new_file(file_id); | 67 | let source = ModuleSource::new_file(file_id.into()); |
68 | if visited.contains(&source) { | 68 | if visited.contains(&source) { |
69 | continue; // TODO: use explicit crate_roots here | 69 | continue; // TODO: use explicit crate_roots here |
70 | } | 70 | } |
@@ -123,7 +123,7 @@ fn build_subtree( | |||
123 | visited, | 123 | visited, |
124 | roots, | 124 | roots, |
125 | Some(link), | 125 | Some(link), |
126 | ModuleSource::new_file(file_id), | 126 | ModuleSource::new_file(file_id.into()), |
127 | ), | 127 | ), |
128 | }) | 128 | }) |
129 | .collect::<Cancelable<Vec<_>>>()?; | 129 | .collect::<Cancelable<Vec<_>>>()?; |
@@ -155,7 +155,7 @@ fn resolve_submodule( | |||
155 | name: &Name, | 155 | name: &Name, |
156 | ) -> (Vec<FileId>, Option<Problem>) { | 156 | ) -> (Vec<FileId>, Option<Problem>) { |
157 | // FIXME: handle submodules of inline modules properly | 157 | // FIXME: handle submodules of inline modules properly |
158 | let file_id = source.file_id(); | 158 | let file_id = source.file_id().original_file(db); |
159 | let source_root_id = db.file_source_root(file_id); | 159 | let source_root_id = db.file_source_root(file_id); |
160 | let path = db.file_relative_path(file_id); | 160 | let path = db.file_relative_path(file_id); |
161 | let root = RelativePathBuf::default(); | 161 | let root = RelativePathBuf::default(); |
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 68eb02a98..40aa33ffa 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -22,10 +22,10 @@ use ra_syntax::{ | |||
22 | SyntaxKind::{self, *}, | 22 | SyntaxKind::{self, *}, |
23 | ast::{self, AstNode} | 23 | ast::{self, AstNode} |
24 | }; | 24 | }; |
25 | use ra_db::SourceRootId; | 25 | use ra_db::{SourceRootId, Cancelable, FileId}; |
26 | 26 | ||
27 | use crate::{ | 27 | use crate::{ |
28 | Cancelable, FileId, | 28 | HirFileId, |
29 | DefId, DefLoc, DefKind, | 29 | DefId, DefLoc, DefKind, |
30 | SourceItemId, SourceFileItemId, SourceFileItems, | 30 | SourceItemId, SourceFileItemId, SourceFileItems, |
31 | Path, PathKind, | 31 | Path, PathKind, |
@@ -70,7 +70,7 @@ pub struct InputModuleItems { | |||
70 | 70 | ||
71 | #[derive(Debug, PartialEq, Eq)] | 71 | #[derive(Debug, PartialEq, Eq)] |
72 | struct ModuleItem { | 72 | struct ModuleItem { |
73 | id: SourceFileItemId, | 73 | id: SourceItemId, |
74 | name: Name, | 74 | name: Name, |
75 | kind: SyntaxKind, | 75 | kind: SyntaxKind, |
76 | vis: Vis, | 76 | vis: Vis, |
@@ -95,9 +95,11 @@ pub struct NamedImport { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | impl NamedImport { | 97 | impl NamedImport { |
98 | // FIXME: this is only here for one use-case in completion. Seems like a | ||
99 | // pretty gross special case. | ||
98 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | 100 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { |
99 | let source_item_id = SourceItemId { | 101 | let source_item_id = SourceItemId { |
100 | file_id, | 102 | file_id: file_id.into(), |
101 | item_id: Some(self.file_item_id), | 103 | item_id: Some(self.file_item_id), |
102 | }; | 104 | }; |
103 | let syntax = db.file_item(source_item_id); | 105 | let syntax = db.file_item(source_item_id); |
@@ -209,24 +211,28 @@ impl<T> PerNs<T> { | |||
209 | } | 211 | } |
210 | 212 | ||
211 | impl InputModuleItems { | 213 | impl InputModuleItems { |
212 | pub(crate) fn new<'a>( | 214 | pub(crate) fn add_item( |
215 | &mut self, | ||
216 | file_id: HirFileId, | ||
213 | file_items: &SourceFileItems, | 217 | file_items: &SourceFileItems, |
214 | items: impl Iterator<Item = ast::ModuleItem<'a>>, | 218 | item: ast::ModuleItem, |
215 | ) -> InputModuleItems { | 219 | ) -> Option<()> { |
216 | let mut res = InputModuleItems::default(); | ||
217 | for item in items { | ||
218 | res.add_item(file_items, item); | ||
219 | } | ||
220 | res | ||
221 | } | ||
222 | |||
223 | fn add_item(&mut self, file_items: &SourceFileItems, item: ast::ModuleItem) -> Option<()> { | ||
224 | match item { | 220 | match item { |
225 | ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 221 | ast::ModuleItem::StructDef(it) => { |
226 | ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 222 | self.items.push(ModuleItem::new(file_id, file_items, it)?) |
227 | ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 223 | } |
228 | ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 224 | ast::ModuleItem::EnumDef(it) => { |
229 | ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 225 | self.items.push(ModuleItem::new(file_id, file_items, it)?) |
226 | } | ||
227 | ast::ModuleItem::FnDef(it) => { | ||
228 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
229 | } | ||
230 | ast::ModuleItem::TraitDef(it) => { | ||
231 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
232 | } | ||
233 | ast::ModuleItem::TypeDef(it) => { | ||
234 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
235 | } | ||
230 | ast::ModuleItem::ImplItem(_) => { | 236 | ast::ModuleItem::ImplItem(_) => { |
231 | // impls don't define items | 237 | // impls don't define items |
232 | } | 238 | } |
@@ -234,9 +240,15 @@ impl InputModuleItems { | |||
234 | ast::ModuleItem::ExternCrateItem(_) => { | 240 | ast::ModuleItem::ExternCrateItem(_) => { |
235 | // TODO | 241 | // TODO |
236 | } | 242 | } |
237 | ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 243 | ast::ModuleItem::ConstDef(it) => { |
238 | ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?), | 244 | self.items.push(ModuleItem::new(file_id, file_items, it)?) |
239 | ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?), | 245 | } |
246 | ast::ModuleItem::StaticDef(it) => { | ||
247 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
248 | } | ||
249 | ast::ModuleItem::Module(it) => { | ||
250 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
251 | } | ||
240 | } | 252 | } |
241 | Some(()) | 253 | Some(()) |
242 | } | 254 | } |
@@ -258,11 +270,16 @@ impl InputModuleItems { | |||
258 | } | 270 | } |
259 | 271 | ||
260 | impl ModuleItem { | 272 | impl ModuleItem { |
261 | fn new<'a>(file_items: &SourceFileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { | 273 | fn new<'a>( |
274 | file_id: HirFileId, | ||
275 | file_items: &SourceFileItems, | ||
276 | item: impl ast::NameOwner<'a>, | ||
277 | ) -> Option<ModuleItem> { | ||
262 | let name = item.name()?.as_name(); | 278 | let name = item.name()?.as_name(); |
263 | let kind = item.syntax().kind(); | 279 | let kind = item.syntax().kind(); |
264 | let vis = Vis::Other; | 280 | let vis = Vis::Other; |
265 | let id = file_items.id_of_unchecked(item.syntax()); | 281 | let item_id = Some(file_items.id_of_unchecked(item.syntax())); |
282 | let id = SourceItemId { file_id, item_id }; | ||
266 | let res = ModuleItem { | 283 | let res = ModuleItem { |
267 | id, | 284 | id, |
268 | name, | 285 | name, |
@@ -302,7 +319,7 @@ where | |||
302 | 319 | ||
303 | pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> { | 320 | pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> { |
304 | for (&module_id, items) in self.input.iter() { | 321 | for (&module_id, items) in self.input.iter() { |
305 | self.populate_module(module_id, items)?; | 322 | self.populate_module(module_id, Arc::clone(items))?; |
306 | } | 323 | } |
307 | 324 | ||
308 | for &module_id in self.input.keys() { | 325 | for &module_id in self.input.keys() { |
@@ -312,9 +329,11 @@ where | |||
312 | Ok(self.result) | 329 | Ok(self.result) |
313 | } | 330 | } |
314 | 331 | ||
315 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) -> Cancelable<()> { | 332 | fn populate_module( |
316 | let file_id = module_id.source(&self.module_tree).file_id(); | 333 | &mut self, |
317 | 334 | module_id: ModuleId, | |
335 | input: Arc<InputModuleItems>, | ||
336 | ) -> Cancelable<()> { | ||
318 | let mut module_items = ModuleScope::default(); | 337 | let mut module_items = ModuleScope::default(); |
319 | 338 | ||
320 | // Populate extern crates prelude | 339 | // Populate extern crates prelude |
@@ -322,7 +341,8 @@ where | |||
322 | let root_id = module_id.crate_root(&self.module_tree); | 341 | let root_id = module_id.crate_root(&self.module_tree); |
323 | let file_id = root_id.source(&self.module_tree).file_id(); | 342 | let file_id = root_id.source(&self.module_tree).file_id(); |
324 | let crate_graph = self.db.crate_graph(); | 343 | let crate_graph = self.db.crate_graph(); |
325 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id) { | 344 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) |
345 | { | ||
326 | let krate = Crate::new(crate_id); | 346 | let krate = Crate::new(crate_id); |
327 | for dep in krate.dependencies(self.db) { | 347 | for dep in krate.dependencies(self.db) { |
328 | if let Some(module) = dep.krate.root_module(self.db)? { | 348 | if let Some(module) = dep.krate.root_module(self.db)? { |
@@ -362,10 +382,7 @@ where | |||
362 | kind: k, | 382 | kind: k, |
363 | source_root_id: self.source_root, | 383 | source_root_id: self.source_root, |
364 | module_id, | 384 | module_id, |
365 | source_item_id: SourceItemId { | 385 | source_item_id: item.id, |
366 | file_id, | ||
367 | item_id: Some(item.id), | ||
368 | }, | ||
369 | }; | 386 | }; |
370 | def_loc.id(self.db) | 387 | def_loc.id(self.db) |
371 | }); | 388 | }); |
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs index ca20f064f..a6a0bea31 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/module/nameres/tests.rs | |||
@@ -78,6 +78,35 @@ fn item_map_smoke_test() { | |||
78 | } | 78 | } |
79 | 79 | ||
80 | #[test] | 80 | #[test] |
81 | fn item_map_contains_items_from_expansions() { | ||
82 | let (item_map, module_id) = item_map( | ||
83 | " | ||
84 | //- /lib.rs | ||
85 | mod foo; | ||
86 | |||
87 | use crate::foo::bar::Baz; | ||
88 | <|> | ||
89 | |||
90 | //- /foo/mod.rs | ||
91 | pub mod bar; | ||
92 | |||
93 | //- /foo/bar.rs | ||
94 | salsa::query_group! { | ||
95 | trait Baz {} | ||
96 | } | ||
97 | ", | ||
98 | ); | ||
99 | check_module_item_map( | ||
100 | &item_map, | ||
101 | module_id, | ||
102 | " | ||
103 | Baz: t | ||
104 | foo: t | ||
105 | ", | ||
106 | ); | ||
107 | } | ||
108 | |||
109 | #[test] | ||
81 | fn item_map_using_self() { | 110 | fn item_map_using_self() { |
82 | let (item_map, module_id) = item_map( | 111 | let (item_map, module_id) = item_map( |
83 | " | 112 | " |
@@ -144,6 +173,59 @@ fn typing_inside_a_function_should_not_invalidate_item_map() { | |||
144 | let (mut db, pos) = MockDatabase::with_position( | 173 | let (mut db, pos) = MockDatabase::with_position( |
145 | " | 174 | " |
146 | //- /lib.rs | 175 | //- /lib.rs |
176 | mod foo; | ||
177 | |||
178 | use crate::foo::bar::Baz; | ||
179 | |||
180 | //- /foo/mod.rs | ||
181 | pub mod bar; | ||
182 | |||
183 | //- /foo/bar.rs | ||
184 | <|> | ||
185 | salsa::query_group! { | ||
186 | trait Baz { | ||
187 | fn foo() -> i32 { 1 + 1 } | ||
188 | } | ||
189 | } | ||
190 | ", | ||
191 | ); | ||
192 | let source_root = db.file_source_root(pos.file_id); | ||
193 | { | ||
194 | let events = db.log_executed(|| { | ||
195 | db.item_map(source_root).unwrap(); | ||
196 | }); | ||
197 | assert!(format!("{:?}", events).contains("item_map")) | ||
198 | } | ||
199 | |||
200 | let new_text = " | ||
201 | salsa::query_group! { | ||
202 | trait Baz { | ||
203 | fn foo() -> i32 { 92 } | ||
204 | } | ||
205 | } | ||
206 | " | ||
207 | .to_string(); | ||
208 | |||
209 | db.query_mut(ra_db::FileTextQuery) | ||
210 | .set(pos.file_id, Arc::new(new_text)); | ||
211 | |||
212 | { | ||
213 | let events = db.log_executed(|| { | ||
214 | db.item_map(source_root).unwrap(); | ||
215 | }); | ||
216 | assert!( | ||
217 | !format!("{:?}", events).contains("item_map"), | ||
218 | "{:#?}", | ||
219 | events | ||
220 | ) | ||
221 | } | ||
222 | } | ||
223 | |||
224 | #[test] | ||
225 | fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() { | ||
226 | let (mut db, pos) = MockDatabase::with_position( | ||
227 | " | ||
228 | //- /lib.rs | ||
147 | mod foo;<|> | 229 | mod foo;<|> |
148 | 230 | ||
149 | use crate::foo::bar::Baz; | 231 | use crate::foo::bar::Baz; |
@@ -183,7 +265,7 @@ fn typing_inside_a_function_should_not_invalidate_item_map() { | |||
183 | db.item_map(source_root).unwrap(); | 265 | db.item_map(source_root).unwrap(); |
184 | }); | 266 | }); |
185 | assert!( | 267 | assert!( |
186 | !format!("{:?}", events).contains("_item_map"), | 268 | !format!("{:?}", events).contains("item_map"), |
187 | "{:#?}", | 269 | "{:#?}", |
188 | events | 270 | events |
189 | ) | 271 | ) |