aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres/raw.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres/raw.rs')
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs482
1 files changed, 0 insertions, 482 deletions
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
deleted file mode 100644
index f44baa579..000000000
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ /dev/null
@@ -1,482 +0,0 @@
1//! Lowers syntax tree of a rust file into a raw representation of containing
2//! items, *without* attaching them to a module structure.
3//!
4//! That is, raw items don't have semantics, just as syntax, but, unlike syntax,
5//! they don't change with trivial source code edits, making them a great tool
6//! for building salsa recomputation firewalls.
7
8use std::{ops::Index, sync::Arc};
9
10use hir_expand::{
11 ast_id_map::AstIdMap,
12 hygiene::Hygiene,
13 name::{AsName, Name},
14};
15use ra_arena::{Arena, Idx};
16use ra_prof::profile;
17use ra_syntax::{
18 ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
19 AstNode,
20};
21use test_utils::mark;
22
23use crate::{
24 attr::Attrs,
25 db::DefDatabase,
26 path::{ImportAlias, ModPath},
27 visibility::RawVisibility,
28 FileAstId, HirFileId, InFile,
29};
30
31/// `RawItems` is a set of top-level items in a file (except for impls).
32///
33/// It is the input to name resolution algorithm. `RawItems` are not invalidated
34/// on most edits.
35#[derive(Debug, Default, PartialEq, Eq)]
36pub struct RawItems {
37 modules: Arena<ModuleData>,
38 imports: Arena<ImportData>,
39 defs: Arena<DefData>,
40 macros: Arena<MacroData>,
41 impls: Arena<ImplData>,
42 /// items for top-level module
43 items: Vec<RawItem>,
44}
45
46impl RawItems {
47 pub(crate) fn raw_items_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<RawItems> {
48 let _p = profile("raw_items_query");
49 let mut collector = RawItemsCollector {
50 raw_items: RawItems::default(),
51 source_ast_id_map: db.ast_id_map(file_id),
52 file_id,
53 hygiene: Hygiene::new(db.upcast(), file_id),
54 };
55 if let Some(node) = db.parse_or_expand(file_id) {
56 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
57 collector.process_module(None, source_file);
58 } else if let Some(item_list) = ast::MacroItems::cast(node) {
59 collector.process_module(None, item_list);
60 }
61 }
62 let raw_items = collector.raw_items;
63 Arc::new(raw_items)
64 }
65
66 pub(super) fn items(&self) -> &[RawItem] {
67 &self.items
68 }
69}
70
71impl Index<Idx<ModuleData>> for RawItems {
72 type Output = ModuleData;
73 fn index(&self, idx: Idx<ModuleData>) -> &ModuleData {
74 &self.modules[idx]
75 }
76}
77
78impl Index<Import> for RawItems {
79 type Output = ImportData;
80 fn index(&self, idx: Import) -> &ImportData {
81 &self.imports[idx]
82 }
83}
84
85impl Index<Idx<DefData>> for RawItems {
86 type Output = DefData;
87 fn index(&self, idx: Idx<DefData>) -> &DefData {
88 &self.defs[idx]
89 }
90}
91
92impl Index<Idx<MacroData>> for RawItems {
93 type Output = MacroData;
94 fn index(&self, idx: Idx<MacroData>) -> &MacroData {
95 &self.macros[idx]
96 }
97}
98
99impl Index<Idx<ImplData>> for RawItems {
100 type Output = ImplData;
101 fn index(&self, idx: Idx<ImplData>) -> &ImplData {
102 &self.impls[idx]
103 }
104}
105
106#[derive(Debug, PartialEq, Eq, Clone)]
107pub(super) struct RawItem {
108 pub(super) attrs: Attrs,
109 pub(super) kind: RawItemKind,
110}
111
112#[derive(Debug, PartialEq, Eq, Clone, Copy)]
113pub(super) enum RawItemKind {
114 Module(Idx<ModuleData>),
115 Import(Import),
116 Def(Idx<DefData>),
117 Macro(Idx<MacroData>),
118 Impl(Idx<ImplData>),
119}
120
121#[derive(Debug, PartialEq, Eq)]
122pub(super) enum ModuleData {
123 Declaration {
124 name: Name,
125 visibility: RawVisibility,
126 ast_id: FileAstId<ast::Module>,
127 },
128 Definition {
129 name: Name,
130 visibility: RawVisibility,
131 ast_id: FileAstId<ast::Module>,
132 items: Vec<RawItem>,
133 },
134}
135
136pub(crate) type Import = Idx<ImportData>;
137
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct ImportData {
140 pub(super) path: ModPath,
141 pub(super) alias: Option<ImportAlias>,
142 pub(super) is_glob: bool,
143 pub(super) is_prelude: bool,
144 pub(super) is_extern_crate: bool,
145 pub(super) is_macro_use: bool,
146 pub(super) visibility: RawVisibility,
147}
148
149// type Def = Idx<DefData>;
150
151#[derive(Debug, PartialEq, Eq)]
152pub(super) struct DefData {
153 pub(super) name: Name,
154 pub(super) kind: DefKind,
155 pub(super) visibility: RawVisibility,
156}
157
158#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum StructDefKind {
160 Record,
161 Tuple,
162 Unit,
163}
164
165#[derive(Debug, PartialEq, Eq, Clone, Copy)]
166pub(super) enum DefKind {
167 Function(FileAstId<ast::FnDef>),
168 Struct(FileAstId<ast::StructDef>, StructDefKind),
169 Union(FileAstId<ast::UnionDef>),
170 Enum(FileAstId<ast::EnumDef>),
171 Const(FileAstId<ast::ConstDef>),
172 Static(FileAstId<ast::StaticDef>),
173 Trait(FileAstId<ast::TraitDef>),
174 TypeAlias(FileAstId<ast::TypeAliasDef>),
175}
176
177impl DefKind {
178 pub fn ast_id(self) -> FileAstId<ast::ModuleItem> {
179 match self {
180 DefKind::Function(it) => it.upcast(),
181 DefKind::Struct(it, _) => it.upcast(),
182 DefKind::Union(it) => it.upcast(),
183 DefKind::Enum(it) => it.upcast(),
184 DefKind::Const(it) => it.upcast(),
185 DefKind::Static(it) => it.upcast(),
186 DefKind::Trait(it) => it.upcast(),
187 DefKind::TypeAlias(it) => it.upcast(),
188 }
189 }
190}
191
192#[derive(Debug, PartialEq, Eq)]
193pub(super) struct MacroData {
194 pub(super) ast_id: FileAstId<ast::MacroCall>,
195 pub(super) path: ModPath,
196 pub(super) name: Option<Name>,
197 pub(super) export: bool,
198 pub(super) local_inner: bool,
199 pub(super) builtin: bool,
200}
201
202#[derive(Debug, PartialEq, Eq)]
203pub(super) struct ImplData {
204 pub(super) ast_id: FileAstId<ast::ImplDef>,
205}
206
207struct RawItemsCollector {
208 raw_items: RawItems,
209 source_ast_id_map: Arc<AstIdMap>,
210 file_id: HirFileId,
211 hygiene: Hygiene,
212}
213
214impl RawItemsCollector {
215 fn process_module(
216 &mut self,
217 current_module: Option<Idx<ModuleData>>,
218 body: impl ast::ModuleItemOwner,
219 ) {
220 for item in body.items() {
221 self.add_item(current_module, item)
222 }
223 }
224
225 fn add_item(&mut self, current_module: Option<Idx<ModuleData>>, item: ast::ModuleItem) {
226 let attrs = self.parse_attrs(&item);
227 let visibility = RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene);
228 let (kind, name) = match item {
229 ast::ModuleItem::Module(module) => {
230 self.add_module(current_module, module);
231 return;
232 }
233 ast::ModuleItem::UseItem(use_item) => {
234 self.add_use_item(current_module, use_item);
235 return;
236 }
237 ast::ModuleItem::ExternCrateItem(extern_crate) => {
238 self.add_extern_crate_item(current_module, extern_crate);
239 return;
240 }
241 ast::ModuleItem::ImplDef(it) => {
242 self.add_impl(current_module, it);
243 return;
244 }
245 ast::ModuleItem::StructDef(it) => {
246 let kind = match it.kind() {
247 ast::StructKind::Record(_) => StructDefKind::Record,
248 ast::StructKind::Tuple(_) => StructDefKind::Tuple,
249 ast::StructKind::Unit => StructDefKind::Unit,
250 };
251 let id = self.source_ast_id_map.ast_id(&it);
252 let name = it.name();
253 (DefKind::Struct(id, kind), name)
254 }
255 ast::ModuleItem::UnionDef(it) => {
256 let id = self.source_ast_id_map.ast_id(&it);
257 let name = it.name();
258 (DefKind::Union(id), name)
259 }
260 ast::ModuleItem::EnumDef(it) => {
261 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
262 }
263 ast::ModuleItem::FnDef(it) => {
264 (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name())
265 }
266 ast::ModuleItem::TraitDef(it) => {
267 (DefKind::Trait(self.source_ast_id_map.ast_id(&it)), it.name())
268 }
269 ast::ModuleItem::TypeAliasDef(it) => {
270 (DefKind::TypeAlias(self.source_ast_id_map.ast_id(&it)), it.name())
271 }
272 ast::ModuleItem::ConstDef(it) => {
273 (DefKind::Const(self.source_ast_id_map.ast_id(&it)), it.name())
274 }
275 ast::ModuleItem::StaticDef(it) => {
276 (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name())
277 }
278 ast::ModuleItem::MacroCall(it) => {
279 self.add_macro(current_module, it);
280 return;
281 }
282 ast::ModuleItem::ExternBlock(it) => {
283 self.add_extern_block(current_module, it);
284 return;
285 }
286 };
287 if let Some(name) = name {
288 let name = name.as_name();
289 let def = self.raw_items.defs.alloc(DefData { name, kind, visibility });
290 self.push_item(current_module, attrs, RawItemKind::Def(def));
291 }
292 }
293
294 fn add_extern_block(
295 &mut self,
296 current_module: Option<Idx<ModuleData>>,
297 block: ast::ExternBlock,
298 ) {
299 if let Some(items) = block.extern_item_list() {
300 for item in items.extern_items() {
301 let attrs = self.parse_attrs(&item);
302 let visibility =
303 RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene);
304 let (kind, name) = match item {
305 ast::ExternItem::FnDef(it) => {
306 (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name())
307 }
308 ast::ExternItem::StaticDef(it) => {
309 (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name())
310 }
311 };
312
313 if let Some(name) = name {
314 let name = name.as_name();
315 let def = self.raw_items.defs.alloc(DefData { name, kind, visibility });
316 self.push_item(current_module, attrs, RawItemKind::Def(def));
317 }
318 }
319 }
320 }
321
322 fn add_module(&mut self, current_module: Option<Idx<ModuleData>>, module: ast::Module) {
323 let name = match module.name() {
324 Some(it) => it.as_name(),
325 None => return,
326 };
327 let attrs = self.parse_attrs(&module);
328 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene);
329
330 let ast_id = self.source_ast_id_map.ast_id(&module);
331 if module.semicolon_token().is_some() {
332 let item =
333 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id });
334 self.push_item(current_module, attrs, RawItemKind::Module(item));
335 return;
336 }
337
338 if let Some(item_list) = module.item_list() {
339 let item = self.raw_items.modules.alloc(ModuleData::Definition {
340 name,
341 visibility,
342 ast_id,
343 items: Vec::new(),
344 });
345 self.process_module(Some(item), item_list);
346 self.push_item(current_module, attrs, RawItemKind::Module(item));
347 return;
348 }
349 mark::hit!(name_res_works_for_broken_modules);
350 }
351
352 fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) {
353 // FIXME: cfg_attr
354 let is_prelude = use_item.has_atom_attr("prelude_import");
355 let attrs = self.parse_attrs(&use_item);
356 let visibility = RawVisibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene);
357
358 let mut buf = Vec::new();
359 ModPath::expand_use_item(
360 InFile { value: use_item, file_id: self.file_id },
361 &self.hygiene,
362 |path, _use_tree, is_glob, alias| {
363 let import_data = ImportData {
364 path,
365 alias,
366 is_glob,
367 is_prelude,
368 is_extern_crate: false,
369 is_macro_use: false,
370 visibility: visibility.clone(),
371 };
372 buf.push(import_data);
373 },
374 );
375 for import_data in buf {
376 self.push_import(current_module, attrs.clone(), import_data);
377 }
378 }
379
380 fn add_extern_crate_item(
381 &mut self,
382 current_module: Option<Idx<ModuleData>>,
383 extern_crate: ast::ExternCrateItem,
384 ) {
385 if let Some(name_ref) = extern_crate.name_ref() {
386 let path = ModPath::from_name_ref(&name_ref);
387 let visibility =
388 RawVisibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene);
389 let alias = extern_crate.alias().map(|a| {
390 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
391 });
392 let attrs = self.parse_attrs(&extern_crate);
393 // FIXME: cfg_attr
394 let is_macro_use = extern_crate.has_atom_attr("macro_use");
395 let import_data = ImportData {
396 path,
397 alias,
398 is_glob: false,
399 is_prelude: false,
400 is_extern_crate: true,
401 is_macro_use,
402 visibility,
403 };
404 self.push_import(current_module, attrs, import_data);
405 }
406 }
407
408 fn add_macro(&mut self, current_module: Option<Idx<ModuleData>>, m: ast::MacroCall) {
409 let attrs = self.parse_attrs(&m);
410 let path = match m.path().and_then(|path| ModPath::from_src(path, &self.hygiene)) {
411 Some(it) => it,
412 _ => return,
413 };
414
415 let name = m.name().map(|it| it.as_name());
416 let ast_id = self.source_ast_id_map.ast_id(&m);
417
418 // FIXME: cfg_attr
419 let export_attr = attrs.by_key("macro_export");
420
421 let export = export_attr.exists();
422 let local_inner = if export {
423 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
424 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
425 ident.text.contains("local_inner_macros")
426 }
427 _ => false,
428 })
429 } else {
430 false
431 };
432
433 let builtin = attrs.by_key("rustc_builtin_macro").exists();
434
435 let m = self.raw_items.macros.alloc(MacroData {
436 ast_id,
437 path,
438 name,
439 export,
440 local_inner,
441 builtin,
442 });
443 self.push_item(current_module, attrs, RawItemKind::Macro(m));
444 }
445
446 fn add_impl(&mut self, current_module: Option<Idx<ModuleData>>, imp: ast::ImplDef) {
447 let attrs = self.parse_attrs(&imp);
448 let ast_id = self.source_ast_id_map.ast_id(&imp);
449 let imp = self.raw_items.impls.alloc(ImplData { ast_id });
450 self.push_item(current_module, attrs, RawItemKind::Impl(imp))
451 }
452
453 fn push_import(
454 &mut self,
455 current_module: Option<Idx<ModuleData>>,
456 attrs: Attrs,
457 data: ImportData,
458 ) {
459 let import = self.raw_items.imports.alloc(data);
460 self.push_item(current_module, attrs, RawItemKind::Import(import))
461 }
462
463 fn push_item(
464 &mut self,
465 current_module: Option<Idx<ModuleData>>,
466 attrs: Attrs,
467 kind: RawItemKind,
468 ) {
469 match current_module {
470 Some(module) => match &mut self.raw_items.modules[module] {
471 ModuleData::Definition { items, .. } => items,
472 ModuleData::Declaration { .. } => unreachable!(),
473 },
474 None => &mut self.raw_items.items,
475 }
476 .push(RawItem { attrs, kind })
477 }
478
479 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
480 Attrs::new(item, &self.hygiene)
481 }
482}