diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/raw.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 403 |
1 files changed, 0 insertions, 403 deletions
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs deleted file mode 100644 index 57f2929c3..000000000 --- a/crates/ra_hir/src/nameres/raw.rs +++ /dev/null | |||
@@ -1,403 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::{ops::Index, sync::Arc}; | ||
4 | |||
5 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | ||
6 | use ra_syntax::{ | ||
7 | ast::{self, AttrsOwner, NameOwner}, | ||
8 | AstNode, AstPtr, SourceFile, | ||
9 | }; | ||
10 | use test_utils::tested_by; | ||
11 | |||
12 | use crate::{ | ||
13 | attr::Attr, | ||
14 | db::{AstDatabase, DefDatabase}, | ||
15 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, | ||
16 | }; | ||
17 | |||
18 | /// `RawItems` is a set of top-level items in a file (except for impls). | ||
19 | /// | ||
20 | /// It is the input to name resolution algorithm. `RawItems` are not invalidated | ||
21 | /// on most edits. | ||
22 | #[derive(Debug, Default, PartialEq, Eq)] | ||
23 | pub struct RawItems { | ||
24 | modules: Arena<Module, ModuleData>, | ||
25 | imports: Arena<ImportId, ImportData>, | ||
26 | defs: Arena<Def, DefData>, | ||
27 | macros: Arena<Macro, MacroData>, | ||
28 | /// items for top-level module | ||
29 | items: Vec<RawItem>, | ||
30 | } | ||
31 | |||
32 | #[derive(Debug, Default, PartialEq, Eq)] | ||
33 | pub struct ImportSourceMap { | ||
34 | map: ArenaMap<ImportId, ImportSourcePtr>, | ||
35 | } | ||
36 | |||
37 | type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; | ||
38 | type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>; | ||
39 | |||
40 | impl ImportSourcePtr { | ||
41 | fn to_node(self, file: &SourceFile) -> ImportSource { | ||
42 | self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax())) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | impl ImportSourceMap { | ||
47 | fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { | ||
48 | self.map.insert(import, ptr) | ||
49 | } | ||
50 | |||
51 | pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource { | ||
52 | let file = match source { | ||
53 | ModuleSource::SourceFile(file) => file.clone(), | ||
54 | ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), | ||
55 | }; | ||
56 | |||
57 | self.map[import].to_node(&file) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | impl RawItems { | ||
62 | pub(crate) fn raw_items_query( | ||
63 | db: &(impl DefDatabase + AstDatabase), | ||
64 | file_id: HirFileId, | ||
65 | ) -> Arc<RawItems> { | ||
66 | db.raw_items_with_source_map(file_id).0 | ||
67 | } | ||
68 | |||
69 | pub(crate) fn raw_items_with_source_map_query( | ||
70 | db: &(impl DefDatabase + AstDatabase), | ||
71 | file_id: HirFileId, | ||
72 | ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { | ||
73 | let mut collector = RawItemsCollector { | ||
74 | raw_items: RawItems::default(), | ||
75 | source_ast_id_map: db.ast_id_map(file_id), | ||
76 | source_map: ImportSourceMap::default(), | ||
77 | file_id, | ||
78 | db, | ||
79 | }; | ||
80 | if let Some(node) = db.parse_or_expand(file_id) { | ||
81 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { | ||
82 | collector.process_module(None, source_file); | ||
83 | } else if let Some(item_list) = ast::MacroItems::cast(node) { | ||
84 | collector.process_module(None, item_list); | ||
85 | } | ||
86 | } | ||
87 | (Arc::new(collector.raw_items), Arc::new(collector.source_map)) | ||
88 | } | ||
89 | |||
90 | pub(super) fn items(&self) -> &[RawItem] { | ||
91 | &self.items | ||
92 | } | ||
93 | } | ||
94 | |||
95 | impl Index<Module> for RawItems { | ||
96 | type Output = ModuleData; | ||
97 | fn index(&self, idx: Module) -> &ModuleData { | ||
98 | &self.modules[idx] | ||
99 | } | ||
100 | } | ||
101 | |||
102 | impl Index<ImportId> for RawItems { | ||
103 | type Output = ImportData; | ||
104 | fn index(&self, idx: ImportId) -> &ImportData { | ||
105 | &self.imports[idx] | ||
106 | } | ||
107 | } | ||
108 | |||
109 | impl Index<Def> for RawItems { | ||
110 | type Output = DefData; | ||
111 | fn index(&self, idx: Def) -> &DefData { | ||
112 | &self.defs[idx] | ||
113 | } | ||
114 | } | ||
115 | |||
116 | impl Index<Macro> for RawItems { | ||
117 | type Output = MacroData; | ||
118 | fn index(&self, idx: Macro) -> &MacroData { | ||
119 | &self.macros[idx] | ||
120 | } | ||
121 | } | ||
122 | |||
123 | // Avoid heap allocation on items without attributes. | ||
124 | type Attrs = Option<Arc<[Attr]>>; | ||
125 | |||
126 | #[derive(Debug, PartialEq, Eq, Clone)] | ||
127 | pub(super) struct RawItem { | ||
128 | attrs: Attrs, | ||
129 | pub(super) kind: RawItemKind, | ||
130 | } | ||
131 | |||
132 | impl RawItem { | ||
133 | pub(super) fn attrs(&self) -> &[Attr] { | ||
134 | self.attrs.as_ref().map_or(&[], |it| &*it) | ||
135 | } | ||
136 | } | ||
137 | |||
138 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
139 | pub(super) enum RawItemKind { | ||
140 | Module(Module), | ||
141 | Import(ImportId), | ||
142 | Def(Def), | ||
143 | Macro(Macro), | ||
144 | } | ||
145 | |||
146 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
147 | pub(super) struct Module(RawId); | ||
148 | impl_arena_id!(Module); | ||
149 | |||
150 | #[derive(Debug, PartialEq, Eq)] | ||
151 | pub(super) enum ModuleData { | ||
152 | Declaration { name: Name, ast_id: FileAstId<ast::Module> }, | ||
153 | Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, | ||
154 | } | ||
155 | |||
156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
157 | pub struct ImportId(RawId); | ||
158 | impl_arena_id!(ImportId); | ||
159 | |||
160 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
161 | pub struct ImportData { | ||
162 | pub(super) path: Path, | ||
163 | pub(super) alias: Option<Name>, | ||
164 | pub(super) is_glob: bool, | ||
165 | pub(super) is_prelude: bool, | ||
166 | pub(super) is_extern_crate: bool, | ||
167 | pub(super) is_macro_use: bool, | ||
168 | } | ||
169 | |||
170 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
171 | pub(super) struct Def(RawId); | ||
172 | impl_arena_id!(Def); | ||
173 | |||
174 | #[derive(Debug, PartialEq, Eq)] | ||
175 | pub(super) struct DefData { | ||
176 | pub(super) name: Name, | ||
177 | pub(super) kind: DefKind, | ||
178 | } | ||
179 | |||
180 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
181 | pub(super) enum DefKind { | ||
182 | Function(FileAstId<ast::FnDef>), | ||
183 | Struct(FileAstId<ast::StructDef>), | ||
184 | Union(FileAstId<ast::StructDef>), | ||
185 | Enum(FileAstId<ast::EnumDef>), | ||
186 | Const(FileAstId<ast::ConstDef>), | ||
187 | Static(FileAstId<ast::StaticDef>), | ||
188 | Trait(FileAstId<ast::TraitDef>), | ||
189 | TypeAlias(FileAstId<ast::TypeAliasDef>), | ||
190 | } | ||
191 | |||
192 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
193 | pub(super) struct Macro(RawId); | ||
194 | impl_arena_id!(Macro); | ||
195 | |||
196 | #[derive(Debug, PartialEq, Eq)] | ||
197 | pub(super) struct MacroData { | ||
198 | pub(super) ast_id: FileAstId<ast::MacroCall>, | ||
199 | pub(super) path: Path, | ||
200 | pub(super) name: Option<Name>, | ||
201 | pub(super) export: bool, | ||
202 | } | ||
203 | |||
204 | struct RawItemsCollector<DB> { | ||
205 | raw_items: RawItems, | ||
206 | source_ast_id_map: Arc<AstIdMap>, | ||
207 | source_map: ImportSourceMap, | ||
208 | file_id: HirFileId, | ||
209 | db: DB, | ||
210 | } | ||
211 | |||
212 | impl<DB: AstDatabase> RawItemsCollector<&DB> { | ||
213 | fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { | ||
214 | for item_or_macro in body.items_with_macros() { | ||
215 | match item_or_macro { | ||
216 | ast::ItemOrMacro::Macro(m) => self.add_macro(current_module, m), | ||
217 | ast::ItemOrMacro::Item(item) => self.add_item(current_module, item), | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { | ||
223 | let attrs = self.parse_attrs(&item); | ||
224 | let (kind, name) = match item { | ||
225 | ast::ModuleItem::Module(module) => { | ||
226 | self.add_module(current_module, module); | ||
227 | return; | ||
228 | } | ||
229 | ast::ModuleItem::UseItem(use_item) => { | ||
230 | self.add_use_item(current_module, use_item); | ||
231 | return; | ||
232 | } | ||
233 | ast::ModuleItem::ExternCrateItem(extern_crate) => { | ||
234 | self.add_extern_crate_item(current_module, extern_crate); | ||
235 | return; | ||
236 | } | ||
237 | ast::ModuleItem::ImplBlock(_) => { | ||
238 | // impls don't participate in name resolution | ||
239 | return; | ||
240 | } | ||
241 | ast::ModuleItem::StructDef(it) => { | ||
242 | let id = self.source_ast_id_map.ast_id(&it); | ||
243 | let name = it.name(); | ||
244 | if it.is_union() { | ||
245 | (DefKind::Union(id), name) | ||
246 | } else { | ||
247 | (DefKind::Struct(id), name) | ||
248 | } | ||
249 | } | ||
250 | ast::ModuleItem::EnumDef(it) => { | ||
251 | (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
252 | } | ||
253 | ast::ModuleItem::FnDef(it) => { | ||
254 | (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
255 | } | ||
256 | ast::ModuleItem::TraitDef(it) => { | ||
257 | (DefKind::Trait(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
258 | } | ||
259 | ast::ModuleItem::TypeAliasDef(it) => { | ||
260 | (DefKind::TypeAlias(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
261 | } | ||
262 | ast::ModuleItem::ConstDef(it) => { | ||
263 | (DefKind::Const(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
264 | } | ||
265 | ast::ModuleItem::StaticDef(it) => { | ||
266 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
267 | } | ||
268 | }; | ||
269 | if let Some(name) = name { | ||
270 | let name = name.as_name(); | ||
271 | let def = self.raw_items.defs.alloc(DefData { name, kind }); | ||
272 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | fn add_module(&mut self, current_module: Option<Module>, module: ast::Module) { | ||
277 | let name = match module.name() { | ||
278 | Some(it) => it.as_name(), | ||
279 | None => return, | ||
280 | }; | ||
281 | let attrs = self.parse_attrs(&module); | ||
282 | |||
283 | let ast_id = self.source_ast_id_map.ast_id(&module); | ||
284 | if module.has_semi() { | ||
285 | let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id }); | ||
286 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | if let Some(item_list) = module.item_list() { | ||
291 | let item = self.raw_items.modules.alloc(ModuleData::Definition { | ||
292 | name, | ||
293 | ast_id, | ||
294 | items: Vec::new(), | ||
295 | }); | ||
296 | self.process_module(Some(item), item_list); | ||
297 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | ||
298 | return; | ||
299 | } | ||
300 | tested_by!(name_res_works_for_broken_modules); | ||
301 | } | ||
302 | |||
303 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { | ||
304 | // FIXME: cfg_attr | ||
305 | let is_prelude = use_item.has_atom_attr("prelude_import"); | ||
306 | let attrs = self.parse_attrs(&use_item); | ||
307 | |||
308 | Path::expand_use_item( | ||
309 | Source { ast: use_item, file_id: self.file_id }, | ||
310 | self.db, | ||
311 | |path, use_tree, is_glob, alias| { | ||
312 | let import_data = ImportData { | ||
313 | path, | ||
314 | alias, | ||
315 | is_glob, | ||
316 | is_prelude, | ||
317 | is_extern_crate: false, | ||
318 | is_macro_use: false, | ||
319 | }; | ||
320 | self.push_import( | ||
321 | current_module, | ||
322 | attrs.clone(), | ||
323 | import_data, | ||
324 | Either::A(AstPtr::new(use_tree)), | ||
325 | ); | ||
326 | }, | ||
327 | ) | ||
328 | } | ||
329 | |||
330 | fn add_extern_crate_item( | ||
331 | &mut self, | ||
332 | current_module: Option<Module>, | ||
333 | extern_crate: ast::ExternCrateItem, | ||
334 | ) { | ||
335 | if let Some(name_ref) = extern_crate.name_ref() { | ||
336 | let path = Path::from_name_ref(&name_ref); | ||
337 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); | ||
338 | let attrs = self.parse_attrs(&extern_crate); | ||
339 | // FIXME: cfg_attr | ||
340 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | ||
341 | let import_data = ImportData { | ||
342 | path, | ||
343 | alias, | ||
344 | is_glob: false, | ||
345 | is_prelude: false, | ||
346 | is_extern_crate: true, | ||
347 | is_macro_use, | ||
348 | }; | ||
349 | self.push_import( | ||
350 | current_module, | ||
351 | attrs, | ||
352 | import_data, | ||
353 | Either::B(AstPtr::new(&extern_crate)), | ||
354 | ); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { | ||
359 | let attrs = self.parse_attrs(&m); | ||
360 | let path = match m | ||
361 | .path() | ||
362 | .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) | ||
363 | { | ||
364 | Some(it) => it, | ||
365 | _ => return, | ||
366 | }; | ||
367 | |||
368 | let name = m.name().map(|it| it.as_name()); | ||
369 | let ast_id = self.source_ast_id_map.ast_id(&m); | ||
370 | // FIXME: cfg_attr | ||
371 | let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); | ||
372 | |||
373 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); | ||
374 | self.push_item(current_module, attrs, RawItemKind::Macro(m)); | ||
375 | } | ||
376 | |||
377 | fn push_import( | ||
378 | &mut self, | ||
379 | current_module: Option<Module>, | ||
380 | attrs: Attrs, | ||
381 | data: ImportData, | ||
382 | source: ImportSourcePtr, | ||
383 | ) { | ||
384 | let import = self.raw_items.imports.alloc(data); | ||
385 | self.source_map.insert(import, source); | ||
386 | self.push_item(current_module, attrs, RawItemKind::Import(import)) | ||
387 | } | ||
388 | |||
389 | fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) { | ||
390 | match current_module { | ||
391 | Some(module) => match &mut self.raw_items.modules[module] { | ||
392 | ModuleData::Definition { items, .. } => items, | ||
393 | ModuleData::Declaration { .. } => unreachable!(), | ||
394 | }, | ||
395 | None => &mut self.raw_items.items, | ||
396 | } | ||
397 | .push(RawItem { attrs, kind }) | ||
398 | } | ||
399 | |||
400 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
401 | Attr::from_attrs_owner(self.file_id, item, self.db) | ||
402 | } | ||
403 | } | ||