diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/attr.rs | 58 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 52 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 21 |
4 files changed, 106 insertions, 26 deletions
diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs new file mode 100644 index 000000000..19be6de32 --- /dev/null +++ b/crates/ra_hir/src/attr.rs | |||
@@ -0,0 +1,58 @@ | |||
1 | use mbe::ast_to_token_tree; | ||
2 | use ra_syntax::{ | ||
3 | ast::{self, AstNode}, | ||
4 | SmolStr, | ||
5 | }; | ||
6 | use tt::Subtree; | ||
7 | |||
8 | use crate::{db::AstDatabase, path::Path, Source}; | ||
9 | |||
10 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
11 | pub(crate) struct Attr { | ||
12 | pub(crate) path: Path, | ||
13 | pub(crate) input: Option<AttrInput>, | ||
14 | } | ||
15 | |||
16 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
17 | pub enum AttrInput { | ||
18 | Literal(SmolStr), | ||
19 | TokenTree(Subtree), | ||
20 | } | ||
21 | |||
22 | impl Attr { | ||
23 | pub(crate) fn from_src( | ||
24 | Source { file_id, ast }: Source<ast::Attr>, | ||
25 | db: &impl AstDatabase, | ||
26 | ) -> Option<Attr> { | ||
27 | let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?; | ||
28 | let input = match ast.input() { | ||
29 | None => None, | ||
30 | Some(ast::AttrInput::Literal(lit)) => { | ||
31 | // FIXME: escape? raw string? | ||
32 | let value = lit.syntax().first_token()?.text().trim_matches('"').into(); | ||
33 | Some(AttrInput::Literal(value)) | ||
34 | } | ||
35 | Some(ast::AttrInput::TokenTree(tt)) => { | ||
36 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | ||
37 | } | ||
38 | }; | ||
39 | |||
40 | Some(Attr { path, input }) | ||
41 | } | ||
42 | |||
43 | pub(crate) fn is_simple_atom(&self, name: &str) -> bool { | ||
44 | // FIXME: Avoid cloning | ||
45 | self.path.as_ident().map_or(false, |s| s.to_string() == name) | ||
46 | } | ||
47 | |||
48 | pub(crate) fn as_cfg(&self) -> Option<&Subtree> { | ||
49 | if self.is_simple_atom("cfg") { | ||
50 | match &self.input { | ||
51 | Some(AttrInput::TokenTree(subtree)) => Some(subtree), | ||
52 | _ => None, | ||
53 | } | ||
54 | } else { | ||
55 | None | ||
56 | } | ||
57 | } | ||
58 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 00031deba..4340e9d34 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -44,6 +44,7 @@ mod traits; | |||
44 | mod type_alias; | 44 | mod type_alias; |
45 | mod type_ref; | 45 | mod type_ref; |
46 | mod ty; | 46 | mod ty; |
47 | mod attr; | ||
47 | mod impl_block; | 48 | mod impl_block; |
48 | mod expr; | 49 | mod expr; |
49 | mod lang_item; | 50 | mod lang_item; |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 40e56dfe0..f0e790e4c 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -1,11 +1,13 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_cfg::CfgOptions; | ||
3 | use ra_db::FileId; | 4 | use ra_db::FileId; |
4 | use ra_syntax::{ast, SmolStr}; | 5 | use ra_syntax::{ast, SmolStr}; |
5 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
6 | use test_utils::tested_by; | 7 | use test_utils::tested_by; |
7 | 8 | ||
8 | use crate::{ | 9 | use crate::{ |
10 | attr::Attr, | ||
9 | db::DefDatabase, | 11 | db::DefDatabase, |
10 | ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, | 12 | ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, |
11 | name::MACRO_RULES, | 13 | name::MACRO_RULES, |
@@ -35,6 +37,9 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
35 | } | 37 | } |
36 | } | 38 | } |
37 | 39 | ||
40 | let crate_graph = db.crate_graph(); | ||
41 | let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id()); | ||
42 | |||
38 | let mut collector = DefCollector { | 43 | let mut collector = DefCollector { |
39 | db, | 44 | db, |
40 | def_map, | 45 | def_map, |
@@ -42,6 +47,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
42 | unresolved_imports: Vec::new(), | 47 | unresolved_imports: Vec::new(), |
43 | unexpanded_macros: Vec::new(), | 48 | unexpanded_macros: Vec::new(), |
44 | macro_stack_monitor: MacroStackMonitor::default(), | 49 | macro_stack_monitor: MacroStackMonitor::default(), |
50 | cfg_options, | ||
45 | }; | 51 | }; |
46 | collector.collect(); | 52 | collector.collect(); |
47 | collector.finish() | 53 | collector.finish() |
@@ -76,8 +82,8 @@ impl MacroStackMonitor { | |||
76 | } | 82 | } |
77 | 83 | ||
78 | /// Walks the tree of module recursively | 84 | /// Walks the tree of module recursively |
79 | struct DefCollector<DB> { | 85 | struct DefCollector<'a, DB> { |
80 | db: DB, | 86 | db: &'a DB, |
81 | def_map: CrateDefMap, | 87 | def_map: CrateDefMap, |
82 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, | 88 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, |
83 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, | 89 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, |
@@ -86,9 +92,11 @@ struct DefCollector<DB> { | |||
86 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly | 92 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly |
87 | /// To prevent stack overflow, we add a deep counter here for prevent that. | 93 | /// To prevent stack overflow, we add a deep counter here for prevent that. |
88 | macro_stack_monitor: MacroStackMonitor, | 94 | macro_stack_monitor: MacroStackMonitor, |
95 | |||
96 | cfg_options: &'a CfgOptions, | ||
89 | } | 97 | } |
90 | 98 | ||
91 | impl<'a, DB> DefCollector<&'a DB> | 99 | impl<DB> DefCollector<'_, DB> |
92 | where | 100 | where |
93 | DB: DefDatabase, | 101 | DB: DefDatabase, |
94 | { | 102 | { |
@@ -506,7 +514,7 @@ struct ModCollector<'a, D> { | |||
506 | parent_module: Option<ParentModule<'a>>, | 514 | parent_module: Option<ParentModule<'a>>, |
507 | } | 515 | } |
508 | 516 | ||
509 | impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> | 517 | impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> |
510 | where | 518 | where |
511 | DB: DefDatabase, | 519 | DB: DefDatabase, |
512 | { | 520 | { |
@@ -523,23 +531,27 @@ where | |||
523 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 531 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
524 | // any other items. | 532 | // any other items. |
525 | for item in items { | 533 | for item in items { |
526 | if let raw::RawItemKind::Import(import_id) = item.kind { | 534 | if self.is_cfg_enabled(&item.attrs) { |
527 | let import = self.raw_items[import_id].clone(); | 535 | if let raw::RawItemKind::Import(import_id) = item.kind { |
528 | if import.is_extern_crate && import.is_macro_use { | 536 | let import = self.raw_items[import_id].clone(); |
529 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | 537 | if import.is_extern_crate && import.is_macro_use { |
538 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | ||
539 | } | ||
530 | } | 540 | } |
531 | } | 541 | } |
532 | } | 542 | } |
533 | 543 | ||
534 | for item in items { | 544 | for item in items { |
535 | match item.kind { | 545 | if self.is_cfg_enabled(&item.attrs) { |
536 | raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), | 546 | match item.kind { |
537 | raw::RawItemKind::Import(import_id) => self | 547 | raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), |
538 | .def_collector | 548 | raw::RawItemKind::Import(import_id) => self |
539 | .unresolved_imports | 549 | .def_collector |
540 | .push((self.module_id, import_id, self.raw_items[import_id].clone())), | 550 | .unresolved_imports |
541 | raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), | 551 | .push((self.module_id, import_id, self.raw_items[import_id].clone())), |
542 | raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), | 552 | raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), |
553 | raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), | ||
554 | } | ||
543 | } | 555 | } |
544 | } | 556 | } |
545 | } | 557 | } |
@@ -702,6 +714,13 @@ where | |||
702 | self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); | 714 | self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); |
703 | } | 715 | } |
704 | } | 716 | } |
717 | |||
718 | fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { | ||
719 | attrs | ||
720 | .iter() | ||
721 | .flat_map(|attr| attr.as_cfg()) | ||
722 | .all(|cfg| self.def_collector.cfg_options.is_cfg_enabled(cfg).unwrap_or(true)) | ||
723 | } | ||
705 | } | 724 | } |
706 | 725 | ||
707 | fn is_macro_rules(path: &Path) -> bool { | 726 | fn is_macro_rules(path: &Path) -> bool { |
@@ -729,6 +748,7 @@ mod tests { | |||
729 | unresolved_imports: Vec::new(), | 748 | unresolved_imports: Vec::new(), |
730 | unexpanded_macros: Vec::new(), | 749 | unexpanded_macros: Vec::new(), |
731 | macro_stack_monitor: monitor, | 750 | macro_stack_monitor: monitor, |
751 | cfg_options: &CfgOptions::default(), | ||
732 | }; | 752 | }; |
733 | collector.collect(); | 753 | collector.collect(); |
734 | collector.finish() | 754 | collector.finish() |
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index cacbcb517..ff079bcf1 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs | |||
@@ -2,7 +2,6 @@ | |||
2 | 2 | ||
3 | use std::{ops::Index, sync::Arc}; | 3 | use std::{ops::Index, sync::Arc}; |
4 | 4 | ||
5 | use mbe::ast_to_token_tree; | ||
6 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | 5 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; |
7 | use ra_syntax::{ | 6 | use ra_syntax::{ |
8 | ast::{self, AttrsOwner, NameOwner}, | 7 | ast::{self, AttrsOwner, NameOwner}, |
@@ -11,6 +10,7 @@ use ra_syntax::{ | |||
11 | use test_utils::tested_by; | 10 | use test_utils::tested_by; |
12 | 11 | ||
13 | use crate::{ | 12 | use crate::{ |
13 | attr::Attr, | ||
14 | db::{AstDatabase, DefDatabase}, | 14 | db::{AstDatabase, DefDatabase}, |
15 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, | 15 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, |
16 | }; | 16 | }; |
@@ -29,8 +29,6 @@ pub struct RawItems { | |||
29 | items: Vec<RawItem>, | 29 | items: Vec<RawItem>, |
30 | } | 30 | } |
31 | 31 | ||
32 | type Attrs = Arc<[tt::Subtree]>; | ||
33 | |||
34 | #[derive(Debug, Default, PartialEq, Eq)] | 32 | #[derive(Debug, Default, PartialEq, Eq)] |
35 | pub struct ImportSourceMap { | 33 | pub struct ImportSourceMap { |
36 | map: ArenaMap<ImportId, ImportSourcePtr>, | 34 | map: ArenaMap<ImportId, ImportSourcePtr>, |
@@ -124,7 +122,7 @@ impl Index<Macro> for RawItems { | |||
124 | 122 | ||
125 | #[derive(Debug, PartialEq, Eq, Clone)] | 123 | #[derive(Debug, PartialEq, Eq, Clone)] |
126 | pub(super) struct RawItem { | 124 | pub(super) struct RawItem { |
127 | pub(super) attrs: Attrs, | 125 | pub(super) attrs: Arc<[Attr]>, |
128 | pub(super) kind: RawItemKind, | 126 | pub(super) kind: RawItemKind, |
129 | } | 127 | } |
130 | 128 | ||
@@ -285,6 +283,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
285 | let attrs = self.parse_attrs(&module); | 283 | let attrs = self.parse_attrs(&module); |
286 | 284 | ||
287 | let ast_id = self.source_ast_id_map.ast_id(&module); | 285 | let ast_id = self.source_ast_id_map.ast_id(&module); |
286 | // FIXME: cfg_attr | ||
288 | let is_macro_use = module.has_atom_attr("macro_use"); | 287 | let is_macro_use = module.has_atom_attr("macro_use"); |
289 | if module.has_semi() { | 288 | if module.has_semi() { |
290 | let attr_path = extract_mod_path_attribute(&module); | 289 | let attr_path = extract_mod_path_attribute(&module); |
@@ -315,6 +314,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
315 | } | 314 | } |
316 | 315 | ||
317 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { | 316 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { |
317 | // FIXME: cfg_attr | ||
318 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 318 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
319 | let attrs = self.parse_attrs(&use_item); | 319 | let attrs = self.parse_attrs(&use_item); |
320 | 320 | ||
@@ -349,6 +349,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
349 | let path = Path::from_name_ref(&name_ref); | 349 | let path = Path::from_name_ref(&name_ref); |
350 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); | 350 | let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); |
351 | let attrs = self.parse_attrs(&extern_crate); | 351 | let attrs = self.parse_attrs(&extern_crate); |
352 | // FIXME: cfg_attr | ||
352 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | 353 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); |
353 | let import_data = ImportData { | 354 | let import_data = ImportData { |
354 | path, | 355 | path, |
@@ -368,6 +369,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
368 | } | 369 | } |
369 | 370 | ||
370 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { | 371 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { |
372 | let attrs = self.parse_attrs(&m); | ||
371 | let path = match m | 373 | let path = match m |
372 | .path() | 374 | .path() |
373 | .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) | 375 | .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) |
@@ -378,6 +380,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
378 | 380 | ||
379 | let name = m.name().map(|it| it.as_name()); | 381 | let name = m.name().map(|it| it.as_name()); |
380 | let ast_id = self.source_ast_id_map.ast_id(&m); | 382 | let ast_id = self.source_ast_id_map.ast_id(&m); |
383 | // FIXME: cfg_attr | ||
381 | let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); | 384 | let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); |
382 | 385 | ||
383 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); | 386 | let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); |
@@ -387,7 +390,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
387 | fn push_import( | 390 | fn push_import( |
388 | &mut self, | 391 | &mut self, |
389 | current_module: Option<Module>, | 392 | current_module: Option<Module>, |
390 | attrs: Attrs, | 393 | attrs: Arc<[Attr]>, |
391 | data: ImportData, | 394 | data: ImportData, |
392 | source: ImportSourcePtr, | 395 | source: ImportSourcePtr, |
393 | ) { | 396 | ) { |
@@ -396,7 +399,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
396 | self.push_item(current_module, attrs, RawItemKind::Import(import)) | 399 | self.push_item(current_module, attrs, RawItemKind::Import(import)) |
397 | } | 400 | } |
398 | 401 | ||
399 | fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) { | 402 | fn push_item(&mut self, current_module: Option<Module>, attrs: Arc<[Attr]>, kind: RawItemKind) { |
400 | match current_module { | 403 | match current_module { |
401 | Some(module) => match &mut self.raw_items.modules[module] { | 404 | Some(module) => match &mut self.raw_items.modules[module] { |
402 | ModuleData::Definition { items, .. } => items, | 405 | ModuleData::Definition { items, .. } => items, |
@@ -407,11 +410,9 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> { | |||
407 | .push(RawItem { attrs, kind }) | 410 | .push(RawItem { attrs, kind }) |
408 | } | 411 | } |
409 | 412 | ||
410 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | 413 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Arc<[Attr]> { |
411 | item.attrs() | 414 | item.attrs() |
412 | .flat_map(|attr| attr.value()) | 415 | .flat_map(|ast| Attr::from_src(Source { ast, file_id: self.file_id }, self.db)) |
413 | .flat_map(|tt| ast_to_token_tree(&tt)) | ||
414 | .map(|(tt, _)| tt) | ||
415 | .collect() | 416 | .collect() |
416 | } | 417 | } |
417 | } | 418 | } |