diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/lower.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 160 |
1 files changed, 92 insertions, 68 deletions
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 921ba3c98..270f9ab03 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -2,52 +2,18 @@ use std::sync::Arc; | |||
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, | 4 | SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, |
5 | ast::{self, ModuleItemOwner}, | 5 | ast::{self, ModuleItemOwner, NameOwner}, |
6 | }; | 6 | }; |
7 | use ra_db::SourceRootId; | 7 | use ra_db::SourceRootId; |
8 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | 8 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; |
9 | use rustc_hash::FxHashMap; | ||
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | 12 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, |
12 | HirFileId, MacroCallLoc, AsName, | 13 | HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, |
13 | module_tree::ModuleId | 14 | module_tree::ModuleId |
14 | }; | 15 | }; |
15 | 16 | ||
16 | #[derive(Debug, PartialEq, Eq)] | ||
17 | pub(super) enum Vis { | ||
18 | // Priv, | ||
19 | Other, | ||
20 | } | ||
21 | |||
22 | #[derive(Debug, PartialEq, Eq)] | ||
23 | pub(crate) struct ModuleItem { | ||
24 | pub(crate) id: SourceItemId, | ||
25 | pub(crate) name: Name, | ||
26 | pub(super) kind: SyntaxKind, | ||
27 | pub(super) vis: Vis, | ||
28 | } | ||
29 | |||
30 | impl ModuleItem { | ||
31 | fn new( | ||
32 | file_id: HirFileId, | ||
33 | file_items: &SourceFileItems, | ||
34 | item: &impl ast::NameOwner, | ||
35 | ) -> Option<ModuleItem> { | ||
36 | let name = item.name()?.as_name(); | ||
37 | let kind = item.syntax().kind(); | ||
38 | let vis = Vis::Other; | ||
39 | let item_id = Some(file_items.id_of_unchecked(item.syntax())); | ||
40 | let id = SourceItemId { file_id, item_id }; | ||
41 | let res = ModuleItem { | ||
42 | id, | ||
43 | name, | ||
44 | kind, | ||
45 | vis, | ||
46 | }; | ||
47 | Some(res) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
52 | pub struct ImportId(RawId); | 18 | pub struct ImportId(RawId); |
53 | impl_arena_id!(ImportId); | 19 | impl_arena_id!(ImportId); |
@@ -66,7 +32,7 @@ pub(super) struct ImportData { | |||
66 | /// can avoid redoing name resolution. | 32 | /// can avoid redoing name resolution. |
67 | #[derive(Debug, Default, PartialEq, Eq)] | 33 | #[derive(Debug, Default, PartialEq, Eq)] |
68 | pub struct LoweredModule { | 34 | pub struct LoweredModule { |
69 | pub(crate) items: Vec<ModuleItem>, | 35 | pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>, |
70 | pub(super) imports: Arena<ImportId, ImportData>, | 36 | pub(super) imports: Arena<ImportId, ImportData>, |
71 | } | 37 | } |
72 | 38 | ||
@@ -157,7 +123,15 @@ impl LoweredModule { | |||
157 | for item in items { | 123 | for item in items { |
158 | match item { | 124 | match item { |
159 | ast::ItemOrMacro::Item(it) => { | 125 | ast::ItemOrMacro::Item(it) => { |
160 | self.add_item(source_map, file_id, &file_items, it); | 126 | self.add_def_id( |
127 | source_map, | ||
128 | db, | ||
129 | source_root_id, | ||
130 | module_id, | ||
131 | file_id, | ||
132 | &file_items, | ||
133 | it, | ||
134 | ); | ||
161 | } | 135 | } |
162 | ast::ItemOrMacro::Macro(macro_call) => { | 136 | ast::ItemOrMacro::Macro(macro_call) => { |
163 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | 137 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); |
@@ -174,54 +148,60 @@ impl LoweredModule { | |||
174 | let file_items = db.file_items(file_id); | 148 | let file_items = db.file_items(file_id); |
175 | //FIXME: expand recursively | 149 | //FIXME: expand recursively |
176 | for item in db.hir_source_file(file_id).items() { | 150 | for item in db.hir_source_file(file_id).items() { |
177 | self.add_item(source_map, file_id, &file_items, item); | 151 | self.add_def_id( |
152 | source_map, | ||
153 | db, | ||
154 | source_root_id, | ||
155 | module_id, | ||
156 | file_id, | ||
157 | &file_items, | ||
158 | item, | ||
159 | ); | ||
178 | } | 160 | } |
179 | } | 161 | } |
180 | } | 162 | } |
181 | } | 163 | } |
182 | } | 164 | } |
183 | 165 | ||
184 | fn add_item( | 166 | fn add_def_id( |
185 | &mut self, | 167 | &mut self, |
186 | source_map: &mut ImportSourceMap, | 168 | source_map: &mut ImportSourceMap, |
169 | db: &impl HirDatabase, | ||
170 | source_root_id: SourceRootId, | ||
171 | module_id: ModuleId, | ||
187 | file_id: HirFileId, | 172 | file_id: HirFileId, |
188 | file_items: &SourceFileItems, | 173 | file_items: &SourceFileItems, |
189 | item: &ast::ModuleItem, | 174 | item: &ast::ModuleItem, |
190 | ) -> Option<()> { | 175 | ) { |
191 | match item.kind() { | 176 | let name = match item.kind() { |
192 | ast::ModuleItemKind::StructDef(it) => { | 177 | ast::ModuleItemKind::StructDef(it) => it.name(), |
193 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | 178 | ast::ModuleItemKind::EnumDef(it) => it.name(), |
194 | } | 179 | ast::ModuleItemKind::FnDef(it) => it.name(), |
195 | ast::ModuleItemKind::EnumDef(it) => { | 180 | ast::ModuleItemKind::TraitDef(it) => it.name(), |
196 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | 181 | ast::ModuleItemKind::TypeDef(it) => it.name(), |
197 | } | ||
198 | ast::ModuleItemKind::FnDef(it) => { | ||
199 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
200 | } | ||
201 | ast::ModuleItemKind::TraitDef(it) => { | ||
202 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
203 | } | ||
204 | ast::ModuleItemKind::TypeDef(it) => { | ||
205 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
206 | } | ||
207 | ast::ModuleItemKind::ImplBlock(_) => { | 182 | ast::ModuleItemKind::ImplBlock(_) => { |
208 | // impls don't define items | 183 | // impls don't define items |
184 | return; | ||
185 | } | ||
186 | ast::ModuleItemKind::UseItem(it) => { | ||
187 | self.add_use_item(source_map, it); | ||
188 | return; | ||
209 | } | 189 | } |
210 | ast::ModuleItemKind::UseItem(it) => self.add_use_item(source_map, it), | ||
211 | ast::ModuleItemKind::ExternCrateItem(_) => { | 190 | ast::ModuleItemKind::ExternCrateItem(_) => { |
212 | // TODO | 191 | // TODO |
192 | return; | ||
213 | } | 193 | } |
214 | ast::ModuleItemKind::ConstDef(it) => { | 194 | ast::ModuleItemKind::ConstDef(it) => it.name(), |
215 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | 195 | ast::ModuleItemKind::StaticDef(it) => it.name(), |
216 | } | 196 | ast::ModuleItemKind::Module(_) => { |
217 | ast::ModuleItemKind::StaticDef(it) => { | 197 | // modules are handled separately direclty by nameres |
218 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | 198 | return; |
219 | } | ||
220 | ast::ModuleItemKind::Module(it) => { | ||
221 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
222 | } | 199 | } |
200 | }; | ||
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); | ||
223 | } | 204 | } |
224 | Some(()) | ||
225 | } | 205 | } |
226 | 206 | ||
227 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | 207 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { |
@@ -236,3 +216,47 @@ impl LoweredModule { | |||
236 | }) | 216 | }) |
237 | } | 217 | } |
238 | } | 218 | } |
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 | // These define items, but don't have their own DefKinds yet: | ||
255 | SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), | ||
256 | SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), | ||
257 | SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const), | ||
258 | SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static), | ||
259 | _ => PerNs::none(), | ||
260 | } | ||
261 | } | ||
262 | } | ||