diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-29 23:52:15 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-10-02 19:28:02 +0100 |
commit | b1ed887d813bf5775a16624694939fdf836f97b1 (patch) | |
tree | b69daa2ca7d29a3362e9608ad0596de18caffa18 /crates | |
parent | ffe179a73663b111e4b3ee8a3f525fb3e461c78e (diff) |
Introduce ra_cfg to parse and evaluate CfgExpr
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_cfg/Cargo.toml | 14 | ||||
-rw-r--r-- | crates/ra_cfg/src/cfg_expr.rs | 128 | ||||
-rw-r--r-- | crates/ra_cfg/src/lib.rs | 43 | ||||
-rw-r--r-- | crates/ra_db/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_db/src/input.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/Cargo.toml | 1 | ||||
-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 |
10 files changed, 301 insertions, 27 deletions
diff --git a/crates/ra_cfg/Cargo.toml b/crates/ra_cfg/Cargo.toml new file mode 100644 index 000000000..b28affc3a --- /dev/null +++ b/crates/ra_cfg/Cargo.toml | |||
@@ -0,0 +1,14 @@ | |||
1 | [package] | ||
2 | edition = "2018" | ||
3 | name = "ra_cfg" | ||
4 | version = "0.1.0" | ||
5 | authors = ["rust-analyzer developers"] | ||
6 | |||
7 | [dependencies] | ||
8 | rustc-hash = "1.0.1" | ||
9 | |||
10 | ra_syntax = { path = "../ra_syntax" } | ||
11 | tt = { path = "../ra_tt", package = "ra_tt" } | ||
12 | |||
13 | [dev-dependencies] | ||
14 | mbe = { path = "../ra_mbe", package = "ra_mbe" } | ||
diff --git a/crates/ra_cfg/src/cfg_expr.rs b/crates/ra_cfg/src/cfg_expr.rs new file mode 100644 index 000000000..efeadf462 --- /dev/null +++ b/crates/ra_cfg/src/cfg_expr.rs | |||
@@ -0,0 +1,128 @@ | |||
1 | use std::slice::Iter as SliceIter; | ||
2 | |||
3 | use ra_syntax::SmolStr; | ||
4 | use tt::{Leaf, Subtree, TokenTree}; | ||
5 | |||
6 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
7 | pub enum CfgExpr { | ||
8 | Invalid, | ||
9 | Atom(SmolStr), | ||
10 | KeyValue { key: SmolStr, value: SmolStr }, | ||
11 | All(Vec<CfgExpr>), | ||
12 | Any(Vec<CfgExpr>), | ||
13 | Not(Box<CfgExpr>), | ||
14 | } | ||
15 | |||
16 | impl CfgExpr { | ||
17 | /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates. | ||
18 | pub fn fold(&self, query: &impl Fn(&SmolStr, Option<&SmolStr>) -> bool) -> Option<bool> { | ||
19 | match self { | ||
20 | CfgExpr::Invalid => None, | ||
21 | CfgExpr::Atom(name) => Some(query(name, None)), | ||
22 | CfgExpr::KeyValue { key, value } => Some(query(key, Some(value))), | ||
23 | CfgExpr::All(preds) => { | ||
24 | preds.iter().try_fold(true, |s, pred| Some(s && pred.fold(query)?)) | ||
25 | } | ||
26 | CfgExpr::Any(preds) => { | ||
27 | preds.iter().try_fold(false, |s, pred| Some(s || pred.fold(query)?)) | ||
28 | } | ||
29 | CfgExpr::Not(pred) => pred.fold(query).map(|s| !s), | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | pub fn parse_cfg(tt: &Subtree) -> CfgExpr { | ||
35 | next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid) | ||
36 | } | ||
37 | |||
38 | fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> { | ||
39 | let name = match it.next() { | ||
40 | None => return None, | ||
41 | Some(TokenTree::Leaf(Leaf::Ident(ident))) => ident.text.clone(), | ||
42 | Some(_) => return Some(CfgExpr::Invalid), | ||
43 | }; | ||
44 | |||
45 | // Peek | ||
46 | let ret = match it.as_slice().first() { | ||
47 | Some(TokenTree::Leaf(Leaf::Punct(punct))) if punct.char == '=' => { | ||
48 | match it.as_slice().get(1) { | ||
49 | Some(TokenTree::Leaf(Leaf::Literal(literal))) => { | ||
50 | it.next(); | ||
51 | it.next(); | ||
52 | // FIXME: escape? raw string? | ||
53 | let value = | ||
54 | SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"')); | ||
55 | CfgExpr::KeyValue { key: name, value } | ||
56 | } | ||
57 | _ => return Some(CfgExpr::Invalid), | ||
58 | } | ||
59 | } | ||
60 | Some(TokenTree::Subtree(subtree)) => { | ||
61 | it.next(); | ||
62 | let mut sub_it = subtree.token_trees.iter(); | ||
63 | let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it)).collect(); | ||
64 | match name.as_str() { | ||
65 | "all" => CfgExpr::All(subs), | ||
66 | "any" => CfgExpr::Any(subs), | ||
67 | "not" => CfgExpr::Not(Box::new(subs.pop().unwrap_or(CfgExpr::Invalid))), | ||
68 | _ => CfgExpr::Invalid, | ||
69 | } | ||
70 | } | ||
71 | _ => CfgExpr::Atom(name), | ||
72 | }; | ||
73 | |||
74 | // Eat comma separator | ||
75 | if let Some(TokenTree::Leaf(Leaf::Punct(punct))) = it.as_slice().first() { | ||
76 | if punct.char == ',' { | ||
77 | it.next(); | ||
78 | } | ||
79 | } | ||
80 | Some(ret) | ||
81 | } | ||
82 | |||
83 | #[cfg(test)] | ||
84 | mod tests { | ||
85 | use super::*; | ||
86 | |||
87 | use mbe::ast_to_token_tree; | ||
88 | use ra_syntax::ast::{self, AstNode}; | ||
89 | |||
90 | fn assert_parse_result(input: &str, expected: CfgExpr) { | ||
91 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | ||
92 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | ||
93 | let (tt, _) = ast_to_token_tree(&tt).unwrap(); | ||
94 | assert_eq!(parse_cfg(&tt), expected); | ||
95 | } | ||
96 | |||
97 | #[test] | ||
98 | fn test_cfg_expr_parser() { | ||
99 | assert_parse_result("#![cfg(foo)]", CfgExpr::Atom("foo".into())); | ||
100 | assert_parse_result("#![cfg(foo,)]", CfgExpr::Atom("foo".into())); | ||
101 | assert_parse_result( | ||
102 | "#![cfg(not(foo))]", | ||
103 | CfgExpr::Not(Box::new(CfgExpr::Atom("foo".into()))), | ||
104 | ); | ||
105 | assert_parse_result("#![cfg(foo(bar))]", CfgExpr::Invalid); | ||
106 | |||
107 | // Only take the first | ||
108 | assert_parse_result(r#"#![cfg(foo, bar = "baz")]"#, CfgExpr::Atom("foo".into())); | ||
109 | |||
110 | assert_parse_result( | ||
111 | r#"#![cfg(all(foo, bar = "baz"))]"#, | ||
112 | CfgExpr::All(vec![ | ||
113 | CfgExpr::Atom("foo".into()), | ||
114 | CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() }, | ||
115 | ]), | ||
116 | ); | ||
117 | |||
118 | assert_parse_result( | ||
119 | r#"#![cfg(any(not(), all(), , bar = "baz",))]"#, | ||
120 | CfgExpr::Any(vec![ | ||
121 | CfgExpr::Not(Box::new(CfgExpr::Invalid)), | ||
122 | CfgExpr::All(vec![]), | ||
123 | CfgExpr::Invalid, | ||
124 | CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() }, | ||
125 | ]), | ||
126 | ); | ||
127 | } | ||
128 | } | ||
diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs new file mode 100644 index 000000000..fa5822d8a --- /dev/null +++ b/crates/ra_cfg/src/lib.rs | |||
@@ -0,0 +1,43 @@ | |||
1 | //! ra_cfg defines conditional compiling options, `cfg` attibute parser and evaluator | ||
2 | use ra_syntax::SmolStr; | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
4 | |||
5 | mod cfg_expr; | ||
6 | |||
7 | pub use cfg_expr::{parse_cfg, CfgExpr}; | ||
8 | |||
9 | #[derive(Debug, Clone, PartialEq, Eq, Default)] | ||
10 | pub struct CfgOptions { | ||
11 | atoms: FxHashSet<SmolStr>, | ||
12 | features: FxHashSet<SmolStr>, | ||
13 | options: FxHashMap<SmolStr, SmolStr>, | ||
14 | } | ||
15 | |||
16 | impl CfgOptions { | ||
17 | pub fn check(&self, cfg: &CfgExpr) -> Option<bool> { | ||
18 | cfg.fold(&|key, value| match value { | ||
19 | None => self.atoms.contains(key), | ||
20 | Some(value) if key == "feature" => self.features.contains(value), | ||
21 | Some(value) => self.options.get(key).map_or(false, |v| v == value), | ||
22 | }) | ||
23 | } | ||
24 | |||
25 | pub fn is_cfg_enabled(&self, attr: &tt::Subtree) -> Option<bool> { | ||
26 | self.check(&parse_cfg(attr)) | ||
27 | } | ||
28 | |||
29 | pub fn atom(mut self, name: SmolStr) -> CfgOptions { | ||
30 | self.atoms.insert(name); | ||
31 | self | ||
32 | } | ||
33 | |||
34 | pub fn feature(mut self, name: SmolStr) -> CfgOptions { | ||
35 | self.features.insert(name); | ||
36 | self | ||
37 | } | ||
38 | |||
39 | pub fn option(mut self, key: SmolStr, value: SmolStr) -> CfgOptions { | ||
40 | self.options.insert(key, value); | ||
41 | self | ||
42 | } | ||
43 | } | ||
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml index 2fac07bc5..c141f1a88 100644 --- a/crates/ra_db/Cargo.toml +++ b/crates/ra_db/Cargo.toml | |||
@@ -10,4 +10,5 @@ relative-path = "0.4.0" | |||
10 | rustc-hash = "1.0" | 10 | rustc-hash = "1.0" |
11 | 11 | ||
12 | ra_syntax = { path = "../ra_syntax" } | 12 | ra_syntax = { path = "../ra_syntax" } |
13 | ra_cfg = { path = "../ra_cfg" } | ||
13 | ra_prof = { path = "../ra_prof" } | 14 | ra_prof = { path = "../ra_prof" } |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 52f892891..5fd6edd78 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -9,6 +9,7 @@ | |||
9 | use relative_path::{RelativePath, RelativePathBuf}; | 9 | use relative_path::{RelativePath, RelativePathBuf}; |
10 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
11 | 11 | ||
12 | use ra_cfg::CfgOptions; | ||
12 | use ra_syntax::SmolStr; | 13 | use ra_syntax::SmolStr; |
13 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
14 | 15 | ||
@@ -109,11 +110,13 @@ struct CrateData { | |||
109 | file_id: FileId, | 110 | file_id: FileId, |
110 | edition: Edition, | 111 | edition: Edition, |
111 | dependencies: Vec<Dependency>, | 112 | dependencies: Vec<Dependency>, |
113 | cfg_options: CfgOptions, | ||
112 | } | 114 | } |
113 | 115 | ||
114 | impl CrateData { | 116 | impl CrateData { |
115 | fn new(file_id: FileId, edition: Edition) -> CrateData { | 117 | fn new(file_id: FileId, edition: Edition) -> CrateData { |
116 | CrateData { file_id, edition, dependencies: Vec::new() } | 118 | // FIXME: cfg options |
119 | CrateData { file_id, edition, dependencies: Vec::new(), cfg_options: CfgOptions::default() } | ||
117 | } | 120 | } |
118 | 121 | ||
119 | fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { | 122 | fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { |
@@ -141,6 +144,10 @@ impl CrateGraph { | |||
141 | crate_id | 144 | crate_id |
142 | } | 145 | } |
143 | 146 | ||
147 | pub fn cfg_options(&self, crate_id: CrateId) -> &CfgOptions { | ||
148 | &self.arena[&crate_id].cfg_options | ||
149 | } | ||
150 | |||
144 | pub fn add_dep( | 151 | pub fn add_dep( |
145 | &mut self, | 152 | &mut self, |
146 | from: CrateId, | 153 | from: CrateId, |
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index d9bed4dda..cc117f84d 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -15,6 +15,7 @@ once_cell = "1.0.1" | |||
15 | 15 | ||
16 | ra_syntax = { path = "../ra_syntax" } | 16 | ra_syntax = { path = "../ra_syntax" } |
17 | ra_arena = { path = "../ra_arena" } | 17 | ra_arena = { path = "../ra_arena" } |
18 | ra_cfg = { path = "../ra_cfg" } | ||
18 | ra_db = { path = "../ra_db" } | 19 | ra_db = { path = "../ra_db" } |
19 | mbe = { path = "../ra_mbe", package = "ra_mbe" } | 20 | mbe = { path = "../ra_mbe", package = "ra_mbe" } |
20 | tt = { path = "../ra_tt", package = "ra_tt" } | 21 | tt = { path = "../ra_tt", package = "ra_tt" } |
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 | } |