diff options
Diffstat (limited to 'crates/ra_cfg/src/cfg_expr.rs')
-rw-r--r-- | crates/ra_cfg/src/cfg_expr.rs | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/crates/ra_cfg/src/cfg_expr.rs b/crates/ra_cfg/src/cfg_expr.rs index 39d71851c..a4b201e0e 100644 --- a/crates/ra_cfg/src/cfg_expr.rs +++ b/crates/ra_cfg/src/cfg_expr.rs | |||
@@ -33,6 +33,36 @@ impl CfgExpr { | |||
33 | CfgExpr::Not(pred) => pred.fold(query).map(|s| !s), | 33 | CfgExpr::Not(pred) => pred.fold(query).map(|s| !s), |
34 | } | 34 | } |
35 | } | 35 | } |
36 | |||
37 | /// Return minimal features needed | ||
38 | pub fn minimal_features_needed(&self) -> Option<Vec<SmolStr>> { | ||
39 | let mut features = vec![]; | ||
40 | self.collect_minimal_features_needed(&mut features); | ||
41 | if features.is_empty() { | ||
42 | None | ||
43 | } else { | ||
44 | Some(features) | ||
45 | } | ||
46 | } | ||
47 | |||
48 | fn collect_minimal_features_needed(&self, features: &mut Vec<SmolStr>) { | ||
49 | match self { | ||
50 | CfgExpr::KeyValue { key, value } if key == "feature" => features.push(value.clone()), | ||
51 | CfgExpr::All(preds) => { | ||
52 | preds.iter().for_each(|cfg| cfg.collect_minimal_features_needed(features)); | ||
53 | } | ||
54 | CfgExpr::Any(preds) => { | ||
55 | for cfg in preds { | ||
56 | let len_features = features.len(); | ||
57 | cfg.collect_minimal_features_needed(features); | ||
58 | if len_features != features.len() { | ||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | _ => {} | ||
64 | } | ||
65 | } | ||
36 | } | 66 | } |
37 | 67 | ||
38 | pub fn parse_cfg(tt: &Subtree) -> CfgExpr { | 68 | pub fn parse_cfg(tt: &Subtree) -> CfgExpr { |
@@ -88,13 +118,17 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> { | |||
88 | mod tests { | 118 | mod tests { |
89 | use super::*; | 119 | use super::*; |
90 | 120 | ||
91 | use mbe::ast_to_token_tree; | 121 | use mbe::{ast_to_token_tree, TokenMap}; |
92 | use ra_syntax::ast::{self, AstNode}; | 122 | use ra_syntax::ast::{self, AstNode}; |
93 | 123 | ||
94 | fn assert_parse_result(input: &str, expected: CfgExpr) { | 124 | fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) { |
95 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 125 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
96 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 126 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
97 | let (tt, _) = ast_to_token_tree(&tt).unwrap(); | 127 | ast_to_token_tree(&tt).unwrap() |
128 | } | ||
129 | |||
130 | fn assert_parse_result(input: &str, expected: CfgExpr) { | ||
131 | let (tt, _) = get_token_tree_generated(input); | ||
98 | assert_eq!(parse_cfg(&tt), expected); | 132 | assert_eq!(parse_cfg(&tt), expected); |
99 | } | 133 | } |
100 | 134 | ||
@@ -129,4 +163,32 @@ mod tests { | |||
129 | ]), | 163 | ]), |
130 | ); | 164 | ); |
131 | } | 165 | } |
166 | |||
167 | #[test] | ||
168 | fn test_cfg_expr_minimal_features_needed() { | ||
169 | let (subtree, _) = get_token_tree_generated(r#"#![cfg(feature = "baz")]"#); | ||
170 | let cfg_expr = parse_cfg(&subtree); | ||
171 | |||
172 | assert_eq!(cfg_expr.minimal_features_needed().unwrap(), vec![SmolStr::new("baz")]); | ||
173 | |||
174 | let (subtree, _) = | ||
175 | get_token_tree_generated(r#"#![cfg(all(feature = "baz", feature = "foo"))]"#); | ||
176 | let cfg_expr = parse_cfg(&subtree); | ||
177 | |||
178 | assert_eq!( | ||
179 | cfg_expr.minimal_features_needed().unwrap(), | ||
180 | vec![SmolStr::new("baz"), SmolStr::new("foo")] | ||
181 | ); | ||
182 | |||
183 | let (subtree, _) = | ||
184 | get_token_tree_generated(r#"#![cfg(any(feature = "baz", feature = "foo", unix))]"#); | ||
185 | let cfg_expr = parse_cfg(&subtree); | ||
186 | |||
187 | assert_eq!(cfg_expr.minimal_features_needed().unwrap(), vec![SmolStr::new("baz")]); | ||
188 | |||
189 | let (subtree, _) = get_token_tree_generated(r#"#![cfg(foo)]"#); | ||
190 | let cfg_expr = parse_cfg(&subtree); | ||
191 | |||
192 | assert!(cfg_expr.minimal_features_needed().is_none()); | ||
193 | } | ||
132 | } | 194 | } |