diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/per_ns.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 102 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 70 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 105 |
5 files changed, 293 insertions, 46 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index ef7dc6ebe..cef2dc9d2 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -1,3 +1,6 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use ra_cfg::CfgOptions; | ||
1 | use ra_db::FileId; | 4 | use ra_db::FileId; |
2 | use ra_syntax::{ast, SmolStr}; | 5 | use ra_syntax::{ast, SmolStr}; |
3 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
@@ -33,6 +36,9 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
33 | } | 36 | } |
34 | } | 37 | } |
35 | 38 | ||
39 | let crate_graph = db.crate_graph(); | ||
40 | let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id()); | ||
41 | |||
36 | let mut collector = DefCollector { | 42 | let mut collector = DefCollector { |
37 | db, | 43 | db, |
38 | def_map, | 44 | def_map, |
@@ -40,6 +46,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
40 | unresolved_imports: Vec::new(), | 46 | unresolved_imports: Vec::new(), |
41 | unexpanded_macros: Vec::new(), | 47 | unexpanded_macros: Vec::new(), |
42 | macro_stack_monitor: MacroStackMonitor::default(), | 48 | macro_stack_monitor: MacroStackMonitor::default(), |
49 | cfg_options, | ||
43 | }; | 50 | }; |
44 | collector.collect(); | 51 | collector.collect(); |
45 | collector.finish() | 52 | collector.finish() |
@@ -74,8 +81,8 @@ impl MacroStackMonitor { | |||
74 | } | 81 | } |
75 | 82 | ||
76 | /// Walks the tree of module recursively | 83 | /// Walks the tree of module recursively |
77 | struct DefCollector<DB> { | 84 | struct DefCollector<'a, DB> { |
78 | db: DB, | 85 | db: &'a DB, |
79 | def_map: CrateDefMap, | 86 | def_map: CrateDefMap, |
80 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, | 87 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, |
81 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, | 88 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, |
@@ -84,9 +91,11 @@ struct DefCollector<DB> { | |||
84 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly | 91 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly |
85 | /// To prevent stack overflow, we add a deep counter here for prevent that. | 92 | /// To prevent stack overflow, we add a deep counter here for prevent that. |
86 | macro_stack_monitor: MacroStackMonitor, | 93 | macro_stack_monitor: MacroStackMonitor, |
94 | |||
95 | cfg_options: &'a CfgOptions, | ||
87 | } | 96 | } |
88 | 97 | ||
89 | impl<'a, DB> DefCollector<&'a DB> | 98 | impl<DB> DefCollector<'_, DB> |
90 | where | 99 | where |
91 | DB: DefDatabase, | 100 | DB: DefDatabase, |
92 | { | 101 | { |
@@ -504,7 +513,7 @@ struct ModCollector<'a, D> { | |||
504 | parent_module: Option<ParentModule<'a>>, | 513 | parent_module: Option<ParentModule<'a>>, |
505 | } | 514 | } |
506 | 515 | ||
507 | impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> | 516 | impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> |
508 | where | 517 | where |
509 | DB: DefDatabase, | 518 | DB: DefDatabase, |
510 | { | 519 | { |
@@ -521,24 +530,27 @@ where | |||
521 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 530 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
522 | // any other items. | 531 | // any other items. |
523 | for item in items { | 532 | for item in items { |
524 | if let raw::RawItem::Import(import_id) = *item { | 533 | if self.is_cfg_enabled(&item.attrs) { |
525 | let import = self.raw_items[import_id].clone(); | 534 | if let raw::RawItemKind::Import(import_id) = item.kind { |
526 | if import.is_extern_crate && import.is_macro_use { | 535 | let import = self.raw_items[import_id].clone(); |
527 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | 536 | if import.is_extern_crate && import.is_macro_use { |
537 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | ||
538 | } | ||
528 | } | 539 | } |
529 | } | 540 | } |
530 | } | 541 | } |
531 | 542 | ||
532 | for item in items { | 543 | for item in items { |
533 | match *item { | 544 | if self.is_cfg_enabled(&item.attrs) { |
534 | raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), | 545 | match item.kind { |
535 | raw::RawItem::Import(import_id) => self.def_collector.unresolved_imports.push(( | 546 | raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), |
536 | self.module_id, | 547 | raw::RawItemKind::Import(import_id) => self |
537 | import_id, | 548 | .def_collector |
538 | self.raw_items[import_id].clone(), | 549 | .unresolved_imports |
539 | )), | 550 | .push((self.module_id, import_id, self.raw_items[import_id].clone())), |
540 | raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), | 551 | raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), |
541 | raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), | 552 | raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), |
553 | } | ||
542 | } | 554 | } |
543 | } | 555 | } |
544 | } | 556 | } |
@@ -662,7 +674,10 @@ where | |||
662 | // Case 1: macro rules, define a macro in crate-global mutable scope | 674 | // Case 1: macro rules, define a macro in crate-global mutable scope |
663 | if is_macro_rules(&mac.path) { | 675 | if is_macro_rules(&mac.path) { |
664 | if let Some(name) = &mac.name { | 676 | if let Some(name) = &mac.name { |
665 | let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); | 677 | let macro_id = MacroDefId { |
678 | ast_id: mac.ast_id.with_file_id(self.file_id), | ||
679 | krate: self.def_collector.def_map.krate, | ||
680 | }; | ||
666 | let macro_ = MacroDef { id: macro_id }; | 681 | let macro_ = MacroDef { id: macro_id }; |
667 | self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); | 682 | self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); |
668 | } | 683 | } |
@@ -698,6 +713,14 @@ where | |||
698 | self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); | 713 | self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); |
699 | } | 714 | } |
700 | } | 715 | } |
716 | |||
717 | fn is_cfg_enabled(&self, attrs: &raw::Attrs) -> bool { | ||
718 | attrs.as_ref().map_or(true, |attrs| { | ||
719 | attrs | ||
720 | .iter() | ||
721 | .all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) | ||
722 | }) | ||
723 | } | ||
701 | } | 724 | } |
702 | 725 | ||
703 | fn is_macro_rules(path: &Path) -> bool { | 726 | fn is_macro_rules(path: &Path) -> bool { |
@@ -725,6 +748,7 @@ mod tests { | |||
725 | unresolved_imports: Vec::new(), | 748 | unresolved_imports: Vec::new(), |
726 | unexpanded_macros: Vec::new(), | 749 | unexpanded_macros: Vec::new(), |
727 | macro_stack_monitor: monitor, | 750 | macro_stack_monitor: monitor, |
751 | cfg_options: &CfgOptions::default(), | ||
728 | }; | 752 | }; |
729 | collector.collect(); | 753 | collector.collect(); |
730 | collector.finish() | 754 | collector.finish() |
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs index 964da2794..0da6789de 100644 --- a/crates/ra_hir/src/nameres/per_ns.rs +++ b/crates/ra_hir/src/nameres/per_ns.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | use crate::{MacroDef, ModuleDef}; | 3 | use crate::{MacroDef, ModuleDef}; |
2 | 4 | ||
3 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 5 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 29aaddbf1..623b343c4 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | use std::{ops::Index, sync::Arc}; | 3 | use std::{ops::Index, sync::Arc}; |
2 | 4 | ||
3 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | 5 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; |
@@ -8,8 +10,9 @@ use ra_syntax::{ | |||
8 | use test_utils::tested_by; | 10 | use test_utils::tested_by; |
9 | 11 | ||
10 | use crate::{ | 12 | use crate::{ |
13 | attr::Attr, | ||
11 | db::{AstDatabase, DefDatabase}, | 14 | db::{AstDatabase, DefDatabase}, |
12 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, | 15 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, |
13 | }; | 16 | }; |
14 | 17 | ||
15 | /// `RawItems` is a set of top-level items in a file (except for impls). | 18 | /// `RawItems` is a set of top-level items in a file (except for impls). |
@@ -71,6 +74,8 @@ impl RawItems { | |||
71 | raw_items: RawItems::default(), | 74 | raw_items: RawItems::default(), |
72 | source_ast_id_map: db.ast_id_map(file_id), | 75 | source_ast_id_map: db.ast_id_map(file_id), |
73 | source_map: ImportSourceMap::default(), | 76 | source_map: ImportSourceMap::default(), |
77 | file_id, | ||
78 | db, | ||
74 | }; | 79 | }; |
75 | if let Some(node) = db.parse_or_expand(file_id) { | 80 | if let Some(node) = db.parse_or_expand(file_id) { |
76 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { | 81 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { |
@@ -115,8 +120,17 @@ impl Index<Macro> for RawItems { | |||
115 | } | 120 | } |
116 | } | 121 | } |
117 | 122 | ||
123 | // Avoid heap allocation on items without attributes. | ||
124 | pub(super) type Attrs = Option<Arc<[Attr]>>; | ||
125 | |||
126 | #[derive(Debug, PartialEq, Eq, Clone)] | ||
127 | pub(super) struct RawItem { | ||
128 | pub(super) attrs: Attrs, | ||
129 | pub(super) kind: RawItemKind, | ||
130 | } | ||
131 | |||
118 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 132 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
119 | pub(super) enum RawItem { | 133 | pub(super) enum RawItemKind { |
120 | Module(Module), | 134 | Module(Module), |
121 | Import(ImportId), | 135 | Import(ImportId), |
122 | Def(Def), | 136 | Def(Def), |
@@ -192,13 +206,15 @@ pub(super) struct MacroData { | |||
192 | pub(super) export: bool, | 206 | pub(super) export: bool, |
193 | } | 207 | } |
194 | 208 | ||
195 | struct RawItemsCollector { | 209 | struct RawItemsCollector<DB> { |
196 | raw_items: RawItems, | 210 | raw_items: RawItems, |
197 | source_ast_id_map: Arc<AstIdMap>, | 211 | source_ast_id_map: Arc<AstIdMap>, |
198 | source_map: ImportSourceMap, | 212 | source_map: ImportSourceMap, |
213 | file_id: HirFileId, | ||
214 | db: DB, | ||
199 | } | 215 | } |
200 | 216 | ||
201 | impl RawItemsCollector { | 217 | impl<DB: AstDatabase> RawItemsCollector<&DB> { |
202 | fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { | 218 | fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { |
203 | for item_or_macro in body.items_with_macros() { | 219 | for item_or_macro in body.items_with_macros() { |
204 | match item_or_macro { | 220 | match item_or_macro { |
@@ -209,6 +225,7 @@ impl RawItemsCollector { | |||
209 | } | 225 | } |
210 | 226 | ||
211 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { | 227 | fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { |
228 | let attrs = self.parse_attrs(&item); | ||
212 | let (kind, name) = match item { | 229 | let (kind, name) = match item { |
213 | ast::ModuleItem::Module(module) => { | 230 | ast::ModuleItem::Module(module) => { |
214 | self.add_module(current_module, module); | 231 | self.add_module(current_module, module); |
@@ -257,7 +274,7 @@ impl RawItemsCollector { | |||
257 | if let Some(name) = name { | 274 | if let Some(name) = name { |
258 | let name = name.as_name(); | 275 | let name = name.as_name(); |
259 | let def = self.raw_items.defs.alloc(DefData { name, kind }); | 276 | let def = self.raw_items.defs.alloc(DefData { name, kind }); |
260 | self.push_item(current_module, RawItem::Def(def)) | 277 | self.push_item(current_module, attrs, RawItemKind::Def(def)); |
261 | } | 278 | } |
262 | } | 279 | } |
263 | 280 | ||
@@ -266,8 +283,10 @@ impl RawItemsCollector { | |||
266 | Some(it) => it.as_name(), | 283 | Some(it) => it.as_name(), |
267 | None => return, | 284 | None => return, |
268 | }; | 285 | }; |
286 | let attrs = self.parse_attrs(&module); | ||
269 | 287 | ||
270 | let ast_id = self.source_ast_id_map.ast_id(&module); | 288 | let ast_id = self.source_ast_id_map.ast_id(&module); |
289 | // FIXME: cfg_attr | ||
271 | let is_macro_use = module.has_atom_attr("macro_use"); | 290 | let is_macro_use = module.has_atom_attr("macro_use"); |
272 | if module.has_semi() { | 291 | if module.has_semi() { |
273 | let attr_path = extract_mod_path_attribute(&module); | 292 | let attr_path = extract_mod_path_attribute(&module); |
@@ -277,7 +296,7 @@ impl RawItemsCollector { | |||
277 | attr_path, | 296 | attr_path, |
278 | is_macro_use, | 297 | is_macro_use, |
279 | }); | 298 | }); |
280 | self.push_item(current_module, RawItem::Module(item)); | 299 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
281 | return; | 300 | return; |
282 | } | 301 | } |
283 | 302 | ||
@@ -291,26 +310,37 @@ impl RawItemsCollector { | |||
291 | is_macro_use, | 310 | is_macro_use, |
292 | }); | 311 | }); |
293 | self.process_module(Some(item), item_list); | 312 | self.process_module(Some(item), item_list); |
294 | self.push_item(current_module, RawItem::Module(item)); | 313 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
295 | return; | 314 | return; |
296 | } | 315 | } |
297 | tested_by!(name_res_works_for_broken_modules); | 316 | tested_by!(name_res_works_for_broken_modules); |
298 | } | 317 | } |
299 | 318 | ||
300 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { | 319 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { |
320 | // FIXME: cfg_attr | ||
301 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 321 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
302 | 322 | let attrs = self.parse_attrs(&use_item); | |
303 | Path::expand_use_item(&use_item, |path, use_tree, is_glob, alias| { | 323 | |
304 | let import_data = ImportData { | 324 | Path::expand_use_item( |
305 | path, | 325 | Source { ast: use_item, file_id: self.file_id }, |
306 | alias, | 326 | self.db, |
307 | is_glob, | 327 | |path, use_tree, is_glob, alias| { |
308 | is_prelude, | 328 | let import_data = ImportData { |
309 | is_extern_crate: false, | 329 | path, |
310 | is_macro_use: false, | 330 | alias, |
311 | }; | 331 | is_glob, |
312 | self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); | 332 | is_prelude, |
313 | }) | 333 | is_extern_crate: false, |
334 | is_macro_use: false, | ||
335 | }; | ||
336 | self.push_import( | ||
337 | current_module, | ||
338 | attrs.clone(), | ||
339 | import_data, | ||
340 | Either::A(AstPtr::new(use_tree)), | ||
341 | ); | ||
342 | }, | ||
343 | ) | ||
314 | } | 344 | } |
315 | 345 | ||
316 | fn add_extern_crate_item( | 346 | fn add_extern_crate_item( |
@@ -321,6 +351,8 @@ impl RawItemsCollector { | |||
321 | if let Some(name_ref) = extern_crate.name_ref() { | 351 | if let Some(name_ref) = extern_crate.name_ref() { |
322 | let path = Path::from_name_ref(&name_ref); | 352 | let path = Path::from_name_ref(&name_ref); |
323 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); | 353 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); |
354 | let attrs = self.parse_attrs(&extern_crate); | ||
355 | // FIXME: cfg_attr | ||
324 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | 356 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); |
325 | let import_data = ImportData { | 357 | let import_data = ImportData { |
326 | path, | 358 | path, |
@@ -330,37 +362,47 @@ impl RawItemsCollector { | |||
330 | is_extern_crate: true, | 362 | is_extern_crate: true, |
331 | is_macro_use, | 363 | is_macro_use, |
332 | }; | 364 | }; |
333 | self.push_import(current_module, import_data, Either::B(AstPtr::new(&extern_crate))); | 365 | self.push_import( |
366 | current_module, | ||
367 | attrs, | ||
368 | import_data, | ||
369 | Either::B(AstPtr::new(&extern_crate)), | ||
370 | ); | ||
334 | } | 371 | } |
335 | } | 372 | } |
336 | 373 | ||
337 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { | 374 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { |
338 | let path = match m.path().and_then(Path::from_ast) { | 375 | let attrs = self.parse_attrs(&m); |
376 | let path = match m | ||
377 | .path() | ||
378 | .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) | ||
379 | { | ||
339 | Some(it) => it, | 380 | Some(it) => it, |
340 | _ => return, | 381 | _ => return, |
341 | }; | 382 | }; |
342 | 383 | ||
343 | let name = m.name().map(|it| it.as_name()); | 384 | let name = m.name().map(|it| it.as_name()); |
344 | let ast_id = self.source_ast_id_map.ast_id(&m); | 385 | let ast_id = self.source_ast_id_map.ast_id(&m); |
345 | let export = m.has_atom_attr("macro_export") | 386 | // FIXME: cfg_attr |
346 | || m.attrs().filter_map(|x| x.as_call()).any(|(name, _)| name == "macro_export"); | 387 | let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); |
347 | 388 | ||
348 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); | 389 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); |
349 | self.push_item(current_module, RawItem::Macro(m)); | 390 | self.push_item(current_module, attrs, RawItemKind::Macro(m)); |
350 | } | 391 | } |
351 | 392 | ||
352 | fn push_import( | 393 | fn push_import( |
353 | &mut self, | 394 | &mut self, |
354 | current_module: Option<Module>, | 395 | current_module: Option<Module>, |
396 | attrs: Attrs, | ||
355 | data: ImportData, | 397 | data: ImportData, |
356 | source: ImportSourcePtr, | 398 | source: ImportSourcePtr, |
357 | ) { | 399 | ) { |
358 | let import = self.raw_items.imports.alloc(data); | 400 | let import = self.raw_items.imports.alloc(data); |
359 | self.source_map.insert(import, source); | 401 | self.source_map.insert(import, source); |
360 | self.push_item(current_module, RawItem::Import(import)) | 402 | self.push_item(current_module, attrs, RawItemKind::Import(import)) |
361 | } | 403 | } |
362 | 404 | ||
363 | fn push_item(&mut self, current_module: Option<Module>, item: RawItem) { | 405 | fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) { |
364 | match current_module { | 406 | match current_module { |
365 | Some(module) => match &mut self.raw_items.modules[module] { | 407 | Some(module) => match &mut self.raw_items.modules[module] { |
366 | ModuleData::Definition { items, .. } => items, | 408 | ModuleData::Definition { items, .. } => items, |
@@ -368,13 +410,17 @@ impl RawItemsCollector { | |||
368 | }, | 410 | }, |
369 | None => &mut self.raw_items.items, | 411 | None => &mut self.raw_items.items, |
370 | } | 412 | } |
371 | .push(item) | 413 | .push(RawItem { attrs, kind }) |
414 | } | ||
415 | |||
416 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
417 | Attr::from_attrs_owner(self.file_id, item, self.db) | ||
372 | } | 418 | } |
373 | } | 419 | } |
374 | 420 | ||
375 | fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> { | 421 | fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> { |
376 | module.attrs().into_iter().find_map(|attr| { | 422 | module.attrs().into_iter().find_map(|attr| { |
377 | attr.as_key_value().and_then(|(name, value)| { | 423 | attr.as_simple_key_value().and_then(|(name, value)| { |
378 | let is_path = name == "path"; | 424 | let is_path = name == "path"; |
379 | if is_path { | 425 | if is_path { |
380 | Some(value) | 426 | Some(value) |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index bc4b47b70..34dd79574 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -7,6 +7,7 @@ mod mod_resolution; | |||
7 | use std::sync::Arc; | 7 | use std::sync::Arc; |
8 | 8 | ||
9 | use insta::assert_snapshot; | 9 | use insta::assert_snapshot; |
10 | use ra_cfg::CfgOptions; | ||
10 | use ra_db::SourceDatabase; | 11 | use ra_db::SourceDatabase; |
11 | use test_utils::covers; | 12 | use test_utils::covers; |
12 | 13 | ||
@@ -507,3 +508,72 @@ fn values_dont_shadow_extern_crates() { | |||
507 | ⋮foo: v | 508 | ⋮foo: v |
508 | "###); | 509 | "###); |
509 | } | 510 | } |
511 | |||
512 | #[test] | ||
513 | fn cfg_not_test() { | ||
514 | let map = def_map_with_crate_graph( | ||
515 | r#" | ||
516 | //- /main.rs | ||
517 | use {Foo, Bar, Baz}; | ||
518 | //- /lib.rs | ||
519 | #[prelude_import] | ||
520 | pub use self::prelude::*; | ||
521 | mod prelude { | ||
522 | #[cfg(test)] | ||
523 | pub struct Foo; | ||
524 | #[cfg(not(test))] | ||
525 | pub struct Bar; | ||
526 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] | ||
527 | pub struct Baz; | ||
528 | } | ||
529 | "#, | ||
530 | crate_graph! { | ||
531 | "main": ("/main.rs", ["std"]), | ||
532 | "std": ("/lib.rs", []), | ||
533 | }, | ||
534 | ); | ||
535 | |||
536 | assert_snapshot!(map, @r###" | ||
537 | ⋮crate | ||
538 | ⋮Bar: t v | ||
539 | ⋮Baz: _ | ||
540 | ⋮Foo: _ | ||
541 | "###); | ||
542 | } | ||
543 | |||
544 | #[test] | ||
545 | fn cfg_test() { | ||
546 | let map = def_map_with_crate_graph( | ||
547 | r#" | ||
548 | //- /main.rs | ||
549 | use {Foo, Bar, Baz}; | ||
550 | //- /lib.rs | ||
551 | #[prelude_import] | ||
552 | pub use self::prelude::*; | ||
553 | mod prelude { | ||
554 | #[cfg(test)] | ||
555 | pub struct Foo; | ||
556 | #[cfg(not(test))] | ||
557 | pub struct Bar; | ||
558 | #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] | ||
559 | pub struct Baz; | ||
560 | } | ||
561 | "#, | ||
562 | crate_graph! { | ||
563 | "main": ("/main.rs", ["std"]), | ||
564 | "std": ("/lib.rs", [], CfgOptions::default() | ||
565 | .atom("test".into()) | ||
566 | .key_value("feature".into(), "foo".into()) | ||
567 | .key_value("feature".into(), "bar".into()) | ||
568 | .key_value("opt".into(), "42".into()) | ||
569 | ), | ||
570 | }, | ||
571 | ); | ||
572 | |||
573 | assert_snapshot!(map, @r###" | ||
574 | ⋮crate | ||
575 | ⋮Bar: _ | ||
576 | ⋮Baz: t v | ||
577 | ⋮Foo: t v | ||
578 | "###); | ||
579 | } | ||
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index bd60f4258..e4b408394 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||
@@ -515,3 +515,108 @@ fn path_qualified_macros() { | |||
515 | ⋮not_found: _ | 515 | ⋮not_found: _ |
516 | "###); | 516 | "###); |
517 | } | 517 | } |
518 | |||
519 | #[test] | ||
520 | fn macro_dollar_crate_is_correct_in_item() { | ||
521 | covers!(macro_dollar_crate_self); | ||
522 | covers!(macro_dollar_crate_other); | ||
523 | let map = def_map_with_crate_graph( | ||
524 | " | ||
525 | //- /main.rs | ||
526 | #[macro_use] | ||
527 | extern crate foo; | ||
528 | |||
529 | #[macro_use] | ||
530 | mod m { | ||
531 | macro_rules! current { | ||
532 | () => { | ||
533 | use $crate::Foo as FooSelf; | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | |||
538 | struct Foo; | ||
539 | |||
540 | current!(); | ||
541 | not_current1!(); | ||
542 | foo::not_current2!(); | ||
543 | |||
544 | //- /lib.rs | ||
545 | mod m { | ||
546 | #[macro_export] | ||
547 | macro_rules! not_current1 { | ||
548 | () => { | ||
549 | use $crate::Bar; | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | |||
554 | #[macro_export] | ||
555 | macro_rules! not_current2 { | ||
556 | () => { | ||
557 | use $crate::Baz; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | struct Bar; | ||
562 | struct Baz; | ||
563 | ", | ||
564 | crate_graph! { | ||
565 | "main": ("/main.rs", ["foo"]), | ||
566 | "foo": ("/lib.rs", []), | ||
567 | }, | ||
568 | ); | ||
569 | assert_snapshot!(map, @r###" | ||
570 | ⋮crate | ||
571 | ⋮Bar: t v | ||
572 | ⋮Baz: t v | ||
573 | ⋮Foo: t v | ||
574 | ⋮FooSelf: t v | ||
575 | ⋮foo: t | ||
576 | ⋮m: t | ||
577 | ⋮ | ||
578 | ⋮crate::m | ||
579 | "###); | ||
580 | } | ||
581 | |||
582 | #[test] | ||
583 | fn macro_dollar_crate_is_correct_in_indirect_deps() { | ||
584 | covers!(macro_dollar_crate_other); | ||
585 | // From std | ||
586 | let map = def_map_with_crate_graph( | ||
587 | r#" | ||
588 | //- /main.rs | ||
589 | foo!(); | ||
590 | |||
591 | //- /std.rs | ||
592 | #[prelude_import] | ||
593 | use self::prelude::*; | ||
594 | |||
595 | pub use core::foo; | ||
596 | |||
597 | mod prelude {} | ||
598 | |||
599 | #[macro_use] | ||
600 | mod std_macros; | ||
601 | |||
602 | //- /core.rs | ||
603 | #[macro_export] | ||
604 | macro_rules! foo { | ||
605 | () => { | ||
606 | use $crate::bar; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | pub struct bar; | ||
611 | "#, | ||
612 | crate_graph! { | ||
613 | "main": ("/main.rs", ["std"]), | ||
614 | "std": ("/std.rs", ["core"]), | ||
615 | "core": ("/core.rs", []), | ||
616 | }, | ||
617 | ); | ||
618 | assert_snapshot!(map, @r###" | ||
619 | ⋮crate | ||
620 | ⋮bar: t v | ||
621 | "###); | ||
622 | } | ||