diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 178 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 35 |
2 files changed, 88 insertions, 125 deletions
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 4eea6ff1d..b4fe99ea7 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -1,17 +1,17 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, | 4 | AstNode, SourceFile, TreeArc, AstPtr, |
5 | ast::{self, ModuleItemOwner, NameOwner}, | 5 | ast::{self, ModuleItemOwner, NameOwner}, |
6 | }; | 6 | }; |
7 | use ra_db::SourceRootId; | ||
8 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | 7 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; |
9 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
10 | 9 | ||
11 | use crate::{ | 10 | use crate::{ |
12 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | 11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, |
13 | HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, |
14 | module_tree::ModuleId | 13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, |
14 | ids::LocationCtx, | ||
15 | }; | 15 | }; |
16 | 16 | ||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -32,7 +32,7 @@ pub(super) struct ImportData { | |||
32 | /// can avoid redoing name resolution. | 32 | /// can avoid redoing name resolution. |
33 | #[derive(Debug, Default, PartialEq, Eq)] | 33 | #[derive(Debug, Default, PartialEq, Eq)] |
34 | pub struct LoweredModule { | 34 | pub struct LoweredModule { |
35 | pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>, | 35 | pub(crate) declarations: FxHashMap<Name, PerNs<ModuleDef>>, |
36 | pub(super) imports: Arena<ImportId, ImportData>, | 36 | pub(super) imports: Arena<ImportId, ImportData>, |
37 | } | 37 | } |
38 | 38 | ||
@@ -59,37 +59,31 @@ impl ImportSourceMap { | |||
59 | impl LoweredModule { | 59 | impl LoweredModule { |
60 | pub(crate) fn lower_module_module_query( | 60 | pub(crate) fn lower_module_module_query( |
61 | db: &impl HirDatabase, | 61 | db: &impl HirDatabase, |
62 | source_root_id: SourceRootId, | 62 | module: Module, |
63 | module_id: ModuleId, | ||
64 | ) -> Arc<LoweredModule> { | 63 | ) -> Arc<LoweredModule> { |
65 | db.lower_module(source_root_id, module_id).0 | 64 | db.lower_module(module).0 |
66 | } | 65 | } |
67 | 66 | ||
68 | pub(crate) fn lower_module_source_map_query( | 67 | pub(crate) fn lower_module_source_map_query( |
69 | db: &impl HirDatabase, | 68 | db: &impl HirDatabase, |
70 | source_root_id: SourceRootId, | 69 | module: Module, |
71 | module_id: ModuleId, | ||
72 | ) -> Arc<ImportSourceMap> { | 70 | ) -> Arc<ImportSourceMap> { |
73 | db.lower_module(source_root_id, module_id).1 | 71 | db.lower_module(module).1 |
74 | } | 72 | } |
75 | 73 | ||
76 | pub(crate) fn lower_module_query( | 74 | pub(crate) fn lower_module_query( |
77 | db: &impl HirDatabase, | 75 | db: &impl HirDatabase, |
78 | source_root_id: SourceRootId, | 76 | module: Module, |
79 | module_id: ModuleId, | ||
80 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | 77 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { |
81 | let module_tree = db.module_tree(source_root_id); | 78 | let (file_id, source) = module.definition_source(db); |
82 | let source = module_id.source(&module_tree); | 79 | let file_id: HirFileId = file_id.into(); |
83 | let file_id = source.file_id; | ||
84 | let source = ModuleSource::from_source_item_id(db, source); | ||
85 | let mut source_map = ImportSourceMap::default(); | 80 | let mut source_map = ImportSourceMap::default(); |
86 | let mut res = LoweredModule::default(); | 81 | let mut res = LoweredModule::default(); |
87 | match source { | 82 | match source { |
88 | ModuleSource::SourceFile(it) => res.fill( | 83 | ModuleSource::SourceFile(it) => res.fill( |
89 | &mut source_map, | 84 | &mut source_map, |
90 | db, | 85 | db, |
91 | source_root_id, | 86 | module, |
92 | module_id, | ||
93 | file_id, | 87 | file_id, |
94 | &mut it.items_with_macros(), | 88 | &mut it.items_with_macros(), |
95 | ), | 89 | ), |
@@ -98,8 +92,7 @@ impl LoweredModule { | |||
98 | res.fill( | 92 | res.fill( |
99 | &mut source_map, | 93 | &mut source_map, |
100 | db, | 94 | db, |
101 | source_root_id, | 95 | module, |
102 | module_id, | ||
103 | file_id, | 96 | file_id, |
104 | &mut item_list.items_with_macros(), | 97 | &mut item_list.items_with_macros(), |
105 | ) | 98 | ) |
@@ -113,8 +106,7 @@ impl LoweredModule { | |||
113 | &mut self, | 106 | &mut self, |
114 | source_map: &mut ImportSourceMap, | 107 | source_map: &mut ImportSourceMap, |
115 | db: &impl HirDatabase, | 108 | db: &impl HirDatabase, |
116 | source_root_id: SourceRootId, | 109 | module: Module, |
117 | module_id: ModuleId, | ||
118 | file_id: HirFileId, | 110 | file_id: HirFileId, |
119 | items: &mut Iterator<Item = ast::ItemOrMacro>, | 111 | items: &mut Iterator<Item = ast::ItemOrMacro>, |
120 | ) { | 112 | ) { |
@@ -123,21 +115,12 @@ impl LoweredModule { | |||
123 | for item in items { | 115 | for item in items { |
124 | match item { | 116 | match item { |
125 | ast::ItemOrMacro::Item(it) => { | 117 | ast::ItemOrMacro::Item(it) => { |
126 | self.add_def_id( | 118 | self.add_def_id(source_map, db, module, file_id, it); |
127 | source_map, | ||
128 | db, | ||
129 | source_root_id, | ||
130 | module_id, | ||
131 | file_id, | ||
132 | &file_items, | ||
133 | it, | ||
134 | ); | ||
135 | } | 119 | } |
136 | ast::ItemOrMacro::Macro(macro_call) => { | 120 | ast::ItemOrMacro::Macro(macro_call) => { |
137 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | 121 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); |
138 | let loc = MacroCallLoc { | 122 | let loc = MacroCallLoc { |
139 | source_root_id, | 123 | module, |
140 | module_id, | ||
141 | source_item_id: SourceItemId { | 124 | source_item_id: SourceItemId { |
142 | file_id, | 125 | file_id, |
143 | item_id: Some(item_id), | 126 | item_id: Some(item_id), |
@@ -145,18 +128,9 @@ impl LoweredModule { | |||
145 | }; | 128 | }; |
146 | let id = loc.id(db); | 129 | let id = loc.id(db); |
147 | let file_id = HirFileId::from(id); | 130 | let file_id = HirFileId::from(id); |
148 | let file_items = db.file_items(file_id); | ||
149 | //FIXME: expand recursively | 131 | //FIXME: expand recursively |
150 | for item in db.hir_source_file(file_id).items() { | 132 | for item in db.hir_source_file(file_id).items() { |
151 | self.add_def_id( | 133 | self.add_def_id(source_map, db, module, file_id, item); |
152 | source_map, | ||
153 | db, | ||
154 | source_root_id, | ||
155 | module_id, | ||
156 | file_id, | ||
157 | &file_items, | ||
158 | item, | ||
159 | ); | ||
160 | } | 134 | } |
161 | } | 135 | } |
162 | } | 136 | } |
@@ -167,41 +141,74 @@ impl LoweredModule { | |||
167 | &mut self, | 141 | &mut self, |
168 | source_map: &mut ImportSourceMap, | 142 | source_map: &mut ImportSourceMap, |
169 | db: &impl HirDatabase, | 143 | db: &impl HirDatabase, |
170 | source_root_id: SourceRootId, | 144 | module: Module, |
171 | module_id: ModuleId, | ||
172 | file_id: HirFileId, | 145 | file_id: HirFileId, |
173 | file_items: &SourceFileItems, | ||
174 | item: &ast::ModuleItem, | 146 | item: &ast::ModuleItem, |
175 | ) { | 147 | ) { |
176 | let name = match item.kind() { | 148 | let ctx = LocationCtx::new(db, module, file_id); |
177 | ast::ModuleItemKind::StructDef(it) => it.name(), | 149 | match item.kind() { |
178 | ast::ModuleItemKind::EnumDef(it) => it.name(), | 150 | ast::ModuleItemKind::StructDef(it) => { |
179 | ast::ModuleItemKind::FnDef(it) => it.name(), | 151 | if let Some(name) = it.name() { |
180 | ast::ModuleItemKind::TraitDef(it) => it.name(), | 152 | let s = Struct { id: ctx.to_def(it) }; |
181 | ast::ModuleItemKind::TypeDef(it) => it.name(), | 153 | let s: ModuleDef = s.into(); |
154 | self.declarations.insert(name.as_name(), PerNs::both(s, s)); | ||
155 | } | ||
156 | } | ||
157 | ast::ModuleItemKind::EnumDef(it) => { | ||
158 | if let Some(name) = it.name() { | ||
159 | let e = Enum { id: ctx.to_def(it) }; | ||
160 | let e: ModuleDef = e.into(); | ||
161 | self.declarations.insert(name.as_name(), PerNs::types(e)); | ||
162 | } | ||
163 | } | ||
164 | ast::ModuleItemKind::FnDef(it) => { | ||
165 | if let Some(name) = it.name() { | ||
166 | let func = Function { id: ctx.to_def(it) }; | ||
167 | self.declarations | ||
168 | .insert(name.as_name(), PerNs::values(func.into())); | ||
169 | } | ||
170 | } | ||
171 | ast::ModuleItemKind::TraitDef(it) => { | ||
172 | if let Some(name) = it.name() { | ||
173 | let t = Trait { id: ctx.to_def(it) }; | ||
174 | self.declarations | ||
175 | .insert(name.as_name(), PerNs::types(t.into())); | ||
176 | } | ||
177 | } | ||
178 | ast::ModuleItemKind::TypeDef(it) => { | ||
179 | if let Some(name) = it.name() { | ||
180 | let t = Type { id: ctx.to_def(it) }; | ||
181 | self.declarations | ||
182 | .insert(name.as_name(), PerNs::types(t.into())); | ||
183 | } | ||
184 | } | ||
182 | ast::ModuleItemKind::ImplBlock(_) => { | 185 | ast::ModuleItemKind::ImplBlock(_) => { |
183 | // impls don't define items | 186 | // impls don't define items |
184 | return; | ||
185 | } | 187 | } |
186 | ast::ModuleItemKind::UseItem(it) => { | 188 | ast::ModuleItemKind::UseItem(it) => { |
187 | self.add_use_item(source_map, it); | 189 | self.add_use_item(source_map, it); |
188 | return; | ||
189 | } | 190 | } |
190 | ast::ModuleItemKind::ExternCrateItem(_) => { | 191 | ast::ModuleItemKind::ExternCrateItem(_) => { |
191 | // TODO | 192 | // TODO |
192 | return; | ||
193 | } | 193 | } |
194 | ast::ModuleItemKind::ConstDef(it) => it.name(), | 194 | ast::ModuleItemKind::ConstDef(it) => { |
195 | ast::ModuleItemKind::StaticDef(it) => it.name(), | 195 | if let Some(name) = it.name() { |
196 | let c = Const { id: ctx.to_def(it) }; | ||
197 | self.declarations | ||
198 | .insert(name.as_name(), PerNs::values(c.into())); | ||
199 | } | ||
200 | } | ||
201 | ast::ModuleItemKind::StaticDef(it) => { | ||
202 | if let Some(name) = it.name() { | ||
203 | let s = Static { id: ctx.to_def(it) }; | ||
204 | self.declarations | ||
205 | .insert(name.as_name(), PerNs::values(s.into())); | ||
206 | } | ||
207 | } | ||
196 | ast::ModuleItemKind::Module(_) => { | 208 | ast::ModuleItemKind::Module(_) => { |
197 | // modules are handled separately direclty by nameres | 209 | // modules are handled separately direclty by nameres |
198 | return; | ||
199 | } | 210 | } |
200 | }; | 211 | }; |
201 | if let Some(name) = name { | ||
202 | let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item); | ||
203 | self.declarations.insert(name.as_name(), def_id); | ||
204 | } | ||
205 | } | 212 | } |
206 | 213 | ||
207 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | 214 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { |
@@ -216,46 +223,3 @@ impl LoweredModule { | |||
216 | }) | 223 | }) |
217 | } | 224 | } |
218 | } | 225 | } |
219 | |||
220 | fn assign_def_id( | ||
221 | db: &impl HirDatabase, | ||
222 | source_root_id: SourceRootId, | ||
223 | module_id: ModuleId, | ||
224 | file_id: HirFileId, | ||
225 | file_items: &SourceFileItems, | ||
226 | item: &ast::ModuleItem, | ||
227 | ) -> PerNs<DefId> { | ||
228 | // depending on the item kind, the location can define something in | ||
229 | // the values namespace, the types namespace, or both | ||
230 | let kind = DefKind::for_syntax_kind(item.syntax().kind()); | ||
231 | let def_id = kind.map(|k| { | ||
232 | let item_id = file_items.id_of_unchecked(item.syntax()); | ||
233 | let def_loc = DefLoc { | ||
234 | kind: k, | ||
235 | source_root_id, | ||
236 | module_id, | ||
237 | source_item_id: SourceItemId { | ||
238 | file_id, | ||
239 | item_id: Some(item_id), | ||
240 | }, | ||
241 | }; | ||
242 | def_loc.id(db) | ||
243 | }); | ||
244 | def_id | ||
245 | } | ||
246 | |||
247 | impl DefKind { | ||
248 | fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> { | ||
249 | match kind { | ||
250 | SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), | ||
251 | SyntaxKind::MODULE => PerNs::types(DefKind::Module), | ||
252 | SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), | ||
253 | SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), | ||
254 | SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), | ||
255 | SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), | ||
256 | SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const), | ||
257 | SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static), | ||
258 | _ => PerNs::none(), | ||
259 | } | ||
260 | } | ||
261 | } | ||
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index e92007453..9322bf08c 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; | 3 | use ra_db::{CrateGraph, SourceRootId, salsa::Database}; |
4 | use relative_path::RelativePath; | 4 | use relative_path::RelativePath; |
5 | use test_utils::{assert_eq_text, covers}; | 5 | use test_utils::{assert_eq_text, covers}; |
6 | 6 | ||
@@ -13,10 +13,10 @@ use crate::{ | |||
13 | 13 | ||
14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | 14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { |
15 | let (db, pos) = MockDatabase::with_position(fixture); | 15 | let (db, pos) = MockDatabase::with_position(fixture); |
16 | let source_root = db.file_source_root(pos.file_id); | ||
17 | let module = crate::source_binder::module_from_position(&db, pos).unwrap(); | 16 | let module = crate::source_binder::module_from_position(&db, pos).unwrap(); |
18 | let module_id = module.def_id.loc(&db).module_id; | 17 | let krate = module.krate(&db).unwrap(); |
19 | (db.item_map(source_root), module_id) | 18 | let module_id = module.module_id; |
19 | (db.item_map(krate.crate_id), module_id) | ||
20 | } | 20 | } |
21 | 21 | ||
22 | fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { | 22 | fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { |
@@ -238,14 +238,13 @@ fn item_map_across_crates() { | |||
238 | 238 | ||
239 | db.set_crate_graph(crate_graph); | 239 | db.set_crate_graph(crate_graph); |
240 | 240 | ||
241 | let source_root = db.file_source_root(main_id); | ||
242 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 241 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
243 | let module_id = module.def_id.loc(&db).module_id; | 242 | let krate = module.krate(&db).unwrap(); |
244 | let item_map = db.item_map(source_root); | 243 | let item_map = db.item_map(krate.crate_id); |
245 | 244 | ||
246 | check_module_item_map( | 245 | check_module_item_map( |
247 | &item_map, | 246 | &item_map, |
248 | module_id, | 247 | module.module_id, |
249 | " | 248 | " |
250 | Baz: t v | 249 | Baz: t v |
251 | test_crate: t | 250 | test_crate: t |
@@ -292,12 +291,12 @@ fn import_across_source_roots() { | |||
292 | db.set_crate_graph(crate_graph); | 291 | db.set_crate_graph(crate_graph); |
293 | 292 | ||
294 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 293 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
295 | let module_id = module.def_id.loc(&db).module_id; | 294 | let krate = module.krate(&db).unwrap(); |
296 | let item_map = db.item_map(source_root); | 295 | let item_map = db.item_map(krate.crate_id); |
297 | 296 | ||
298 | check_module_item_map( | 297 | check_module_item_map( |
299 | &item_map, | 298 | &item_map, |
300 | module_id, | 299 | module.module_id, |
301 | " | 300 | " |
302 | C: t v | 301 | C: t v |
303 | test_crate: t | 302 | test_crate: t |
@@ -333,14 +332,13 @@ fn reexport_across_crates() { | |||
333 | 332 | ||
334 | db.set_crate_graph(crate_graph); | 333 | db.set_crate_graph(crate_graph); |
335 | 334 | ||
336 | let source_root = db.file_source_root(main_id); | ||
337 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 335 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
338 | let module_id = module.def_id.loc(&db).module_id; | 336 | let krate = module.krate(&db).unwrap(); |
339 | let item_map = db.item_map(source_root); | 337 | let item_map = db.item_map(krate.crate_id); |
340 | 338 | ||
341 | check_module_item_map( | 339 | check_module_item_map( |
342 | &item_map, | 340 | &item_map, |
343 | module_id, | 341 | module.module_id, |
344 | " | 342 | " |
345 | Baz: t v | 343 | Baz: t v |
346 | test_crate: t | 344 | test_crate: t |
@@ -350,10 +348,11 @@ fn reexport_across_crates() { | |||
350 | 348 | ||
351 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | 349 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { |
352 | let (mut db, pos) = MockDatabase::with_position(initial); | 350 | let (mut db, pos) = MockDatabase::with_position(initial); |
353 | let source_root = db.file_source_root(pos.file_id); | 351 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); |
352 | let krate = module.krate(&db).unwrap(); | ||
354 | { | 353 | { |
355 | let events = db.log_executed(|| { | 354 | let events = db.log_executed(|| { |
356 | db.item_map(source_root); | 355 | db.item_map(krate.crate_id); |
357 | }); | 356 | }); |
358 | assert!(format!("{:?}", events).contains("item_map")) | 357 | assert!(format!("{:?}", events).contains("item_map")) |
359 | } | 358 | } |
@@ -362,7 +361,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | |||
362 | 361 | ||
363 | { | 362 | { |
364 | let events = db.log_executed(|| { | 363 | let events = db.log_executed(|| { |
365 | db.item_map(source_root); | 364 | db.item_map(krate.crate_id); |
366 | }); | 365 | }); |
367 | assert!( | 366 | assert!( |
368 | !format!("{:?}", events).contains("item_map"), | 367 | !format!("{:?}", events).contains("item_map"), |