aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-29 23:52:15 +0100
committeruHOOCCOOHu <[email protected]>2019-10-02 19:28:02 +0100
commitb1ed887d813bf5775a16624694939fdf836f97b1 (patch)
treeb69daa2ca7d29a3362e9608ad0596de18caffa18 /crates/ra_hir/src
parentffe179a73663b111e4b3ee8a3f525fb3e461c78e (diff)
Introduce ra_cfg to parse and evaluate CfgExpr
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/attr.rs58
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs52
-rw-r--r--crates/ra_hir/src/nameres/raw.rs21
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 @@
1use mbe::ast_to_token_tree;
2use ra_syntax::{
3 ast::{self, AstNode},
4 SmolStr,
5};
6use tt::Subtree;
7
8use crate::{db::AstDatabase, path::Path, Source};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub(crate) struct Attr {
12 pub(crate) path: Path,
13 pub(crate) input: Option<AttrInput>,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum AttrInput {
18 Literal(SmolStr),
19 TokenTree(Subtree),
20}
21
22impl 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;
44mod type_alias; 44mod type_alias;
45mod type_ref; 45mod type_ref;
46mod ty; 46mod ty;
47mod attr;
47mod impl_block; 48mod impl_block;
48mod expr; 49mod expr;
49mod lang_item; 50mod 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
3use ra_cfg::CfgOptions;
3use ra_db::FileId; 4use ra_db::FileId;
4use ra_syntax::{ast, SmolStr}; 5use ra_syntax::{ast, SmolStr};
5use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
6use test_utils::tested_by; 7use test_utils::tested_by;
7 8
8use crate::{ 9use 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
79struct DefCollector<DB> { 85struct 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
91impl<'a, DB> DefCollector<&'a DB> 99impl<DB> DefCollector<'_, DB>
92where 100where
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
509impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 517impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
510where 518where
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
707fn is_macro_rules(path: &Path) -> bool { 726fn 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
3use std::{ops::Index, sync::Arc}; 3use std::{ops::Index, sync::Arc};
4 4
5use mbe::ast_to_token_tree;
6use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 5use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7use ra_syntax::{ 6use ra_syntax::{
8 ast::{self, AttrsOwner, NameOwner}, 7 ast::{self, AttrsOwner, NameOwner},
@@ -11,6 +10,7 @@ use ra_syntax::{
11use test_utils::tested_by; 10use test_utils::tested_by;
12 11
13use crate::{ 12use 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
32type Attrs = Arc<[tt::Subtree]>;
33
34#[derive(Debug, Default, PartialEq, Eq)] 32#[derive(Debug, Default, PartialEq, Eq)]
35pub struct ImportSourceMap { 33pub 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)]
126pub(super) struct RawItem { 124pub(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}