aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/lower.rs178
-rw-r--r--crates/ra_hir/src/nameres/tests.rs35
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use 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};
7use ra_db::SourceRootId;
8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 7use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
9use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
10 9
11use crate::{ 10use 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)]
34pub struct LoweredModule { 34pub 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 {
59impl LoweredModule { 59impl 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
220fn 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
247impl 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; 3use ra_db::{CrateGraph, SourceRootId, salsa::Database};
4use relative_path::RelativePath; 4use relative_path::RelativePath;
5use test_utils::{assert_eq_text, covers}; 5use test_utils::{assert_eq_text, covers};
6 6
@@ -13,10 +13,10 @@ use crate::{
13 13
14fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { 14fn 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
22fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 22fn 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
351fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { 349fn 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"),