diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/lower.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 222 |
1 files changed, 0 insertions, 222 deletions
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs deleted file mode 100644 index 56262ad6d..000000000 --- a/crates/ra_hir/src/nameres/lower.rs +++ /dev/null | |||
@@ -1,222 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_syntax::{ | ||
4 | AstNode, SourceFile, TreeArc, AstPtr, | ||
5 | ast::{self, ModuleItemOwner, NameOwner, AttrsOwner}, | ||
6 | }; | ||
7 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | |||
10 | use crate::{ | ||
11 | SourceItemId, Path, ModuleSource, Name, | ||
12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, | ||
13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | ||
14 | ids::LocationCtx, PersistentHirDatabase, | ||
15 | }; | ||
16 | |||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
18 | pub struct ImportId(RawId); | ||
19 | impl_arena_id!(ImportId); | ||
20 | |||
21 | #[derive(Debug, PartialEq, Eq)] | ||
22 | pub(super) struct ImportData { | ||
23 | pub(super) path: Path, | ||
24 | pub(super) alias: Option<Name>, | ||
25 | pub(super) is_glob: bool, | ||
26 | pub(super) is_prelude: bool, | ||
27 | pub(super) is_extern_crate: bool, | ||
28 | } | ||
29 | |||
30 | /// A set of items and imports declared inside a module, without relation to | ||
31 | /// other modules. | ||
32 | /// | ||
33 | /// This sits in-between raw syntax and name resolution and allows us to avoid | ||
34 | /// recomputing name res: if two instance of `InputModuleItems` are the same, we | ||
35 | /// can avoid redoing name resolution. | ||
36 | #[derive(Debug, Default, PartialEq, Eq)] | ||
37 | pub struct LoweredModule { | ||
38 | pub(crate) declarations: FxHashMap<Name, PerNs<ModuleDef>>, | ||
39 | pub(super) imports: Arena<ImportId, ImportData>, | ||
40 | } | ||
41 | |||
42 | #[derive(Debug, Default, PartialEq, Eq)] | ||
43 | pub struct ImportSourceMap { | ||
44 | map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, | ||
45 | } | ||
46 | |||
47 | impl ImportSourceMap { | ||
48 | fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { | ||
49 | self.map.insert(import, AstPtr::new(segment)) | ||
50 | } | ||
51 | |||
52 | pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { | ||
53 | let file = match source { | ||
54 | ModuleSource::SourceFile(file) => &*file, | ||
55 | ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), | ||
56 | }; | ||
57 | |||
58 | self.map[import].to_node(file).to_owned() | ||
59 | } | ||
60 | } | ||
61 | |||
62 | impl LoweredModule { | ||
63 | pub(crate) fn lower_module_query( | ||
64 | db: &impl PersistentHirDatabase, | ||
65 | module: Module, | ||
66 | ) -> Arc<LoweredModule> { | ||
67 | db.lower_module_with_source_map(module).0 | ||
68 | } | ||
69 | |||
70 | pub(crate) fn lower_module_with_source_map_query( | ||
71 | db: &impl PersistentHirDatabase, | ||
72 | module: Module, | ||
73 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | ||
74 | let (file_id, source) = module.definition_source(db); | ||
75 | let file_id: HirFileId = file_id.into(); | ||
76 | let mut source_map = ImportSourceMap::default(); | ||
77 | let mut res = LoweredModule::default(); | ||
78 | match source { | ||
79 | ModuleSource::SourceFile(it) => { | ||
80 | res.fill(&mut source_map, db, module, file_id, &mut it.items_with_macros()) | ||
81 | } | ||
82 | ModuleSource::Module(it) => { | ||
83 | if let Some(item_list) = it.item_list() { | ||
84 | res.fill( | ||
85 | &mut source_map, | ||
86 | db, | ||
87 | module, | ||
88 | file_id, | ||
89 | &mut item_list.items_with_macros(), | ||
90 | ) | ||
91 | } | ||
92 | } | ||
93 | }; | ||
94 | (Arc::new(res), Arc::new(source_map)) | ||
95 | } | ||
96 | |||
97 | fn fill( | ||
98 | &mut self, | ||
99 | source_map: &mut ImportSourceMap, | ||
100 | db: &impl PersistentHirDatabase, | ||
101 | module: Module, | ||
102 | file_id: HirFileId, | ||
103 | items: &mut Iterator<Item = ast::ItemOrMacro>, | ||
104 | ) { | ||
105 | let file_items = db.file_items(file_id); | ||
106 | |||
107 | for item in items { | ||
108 | match item { | ||
109 | ast::ItemOrMacro::Item(it) => { | ||
110 | self.add_def_id(source_map, db, module, file_id, it); | ||
111 | } | ||
112 | ast::ItemOrMacro::Macro(macro_call) => { | ||
113 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | ||
114 | let loc = | ||
115 | MacroCallLoc { module, source_item_id: SourceItemId { file_id, item_id } }; | ||
116 | let id = loc.id(db); | ||
117 | let file_id = HirFileId::from(id); | ||
118 | //FIXME: expand recursively | ||
119 | for item in db.hir_parse(file_id).items() { | ||
120 | self.add_def_id(source_map, db, module, file_id, item); | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | fn add_def_id( | ||
128 | &mut self, | ||
129 | source_map: &mut ImportSourceMap, | ||
130 | db: &impl PersistentHirDatabase, | ||
131 | module: Module, | ||
132 | file_id: HirFileId, | ||
133 | item: &ast::ModuleItem, | ||
134 | ) { | ||
135 | let ctx = LocationCtx::new(db, module, file_id); | ||
136 | match item.kind() { | ||
137 | ast::ModuleItemKind::StructDef(it) => { | ||
138 | if let Some(name) = it.name() { | ||
139 | let s = Struct { id: ctx.to_def(it) }; | ||
140 | let s: ModuleDef = s.into(); | ||
141 | self.declarations.insert(name.as_name(), PerNs::both(s, s)); | ||
142 | } | ||
143 | } | ||
144 | ast::ModuleItemKind::EnumDef(it) => { | ||
145 | if let Some(name) = it.name() { | ||
146 | let e = Enum { id: ctx.to_def(it) }; | ||
147 | let e: ModuleDef = e.into(); | ||
148 | self.declarations.insert(name.as_name(), PerNs::types(e)); | ||
149 | } | ||
150 | } | ||
151 | ast::ModuleItemKind::FnDef(it) => { | ||
152 | if let Some(name) = it.name() { | ||
153 | let func = Function { id: ctx.to_def(it) }; | ||
154 | self.declarations.insert(name.as_name(), PerNs::values(func.into())); | ||
155 | } | ||
156 | } | ||
157 | ast::ModuleItemKind::TraitDef(it) => { | ||
158 | if let Some(name) = it.name() { | ||
159 | let t = Trait { id: ctx.to_def(it) }; | ||
160 | self.declarations.insert(name.as_name(), PerNs::types(t.into())); | ||
161 | } | ||
162 | } | ||
163 | ast::ModuleItemKind::TypeAliasDef(it) => { | ||
164 | if let Some(name) = it.name() { | ||
165 | let t = TypeAlias { id: ctx.to_def(it) }; | ||
166 | self.declarations.insert(name.as_name(), PerNs::types(t.into())); | ||
167 | } | ||
168 | } | ||
169 | ast::ModuleItemKind::ImplBlock(_) => { | ||
170 | // impls don't define items | ||
171 | } | ||
172 | ast::ModuleItemKind::UseItem(it) => { | ||
173 | self.add_use_item(source_map, it); | ||
174 | } | ||
175 | ast::ModuleItemKind::ExternCrateItem(it) => { | ||
176 | if let Some(name_ref) = it.name_ref() { | ||
177 | let path = Path::from_name_ref(name_ref); | ||
178 | let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name); | ||
179 | self.imports.alloc(ImportData { | ||
180 | path, | ||
181 | alias, | ||
182 | is_glob: false, | ||
183 | is_prelude: false, | ||
184 | is_extern_crate: true, | ||
185 | }); | ||
186 | } | ||
187 | } | ||
188 | ast::ModuleItemKind::ConstDef(it) => { | ||
189 | if let Some(name) = it.name() { | ||
190 | let c = Const { id: ctx.to_def(it) }; | ||
191 | self.declarations.insert(name.as_name(), PerNs::values(c.into())); | ||
192 | } | ||
193 | } | ||
194 | ast::ModuleItemKind::StaticDef(it) => { | ||
195 | if let Some(name) = it.name() { | ||
196 | let s = Static { id: ctx.to_def(it) }; | ||
197 | self.declarations.insert(name.as_name(), PerNs::values(s.into())); | ||
198 | } | ||
199 | } | ||
200 | ast::ModuleItemKind::Module(_) => { | ||
201 | // modules are handled separately directly by name res | ||
202 | } | ||
203 | }; | ||
204 | } | ||
205 | |||
206 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | ||
207 | let is_prelude = | ||
208 | item.attrs().any(|attr| attr.as_atom().map(|s| s == "prelude_import").unwrap_or(false)); | ||
209 | Path::expand_use_item(item, |path, segment, alias| { | ||
210 | let import = self.imports.alloc(ImportData { | ||
211 | path, | ||
212 | alias, | ||
213 | is_glob: segment.is_none(), | ||
214 | is_prelude, | ||
215 | is_extern_crate: false, | ||
216 | }); | ||
217 | if let Some(segment) = segment { | ||
218 | source_map.insert(import, segment) | ||
219 | } | ||
220 | }) | ||
221 | } | ||
222 | } | ||