aboutsummaryrefslogtreecommitdiff
path: root/crates/cfg/src/cfg_expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/cfg/src/cfg_expr.rs')
-rw-r--r--crates/cfg/src/cfg_expr.rs44
1 files changed, 30 insertions, 14 deletions
diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs
index 336fe25bc..db3655b74 100644
--- a/crates/cfg/src/cfg_expr.rs
+++ b/crates/cfg/src/cfg_expr.rs
@@ -6,26 +6,42 @@ use std::slice::Iter as SliceIter;
6 6
7use tt::SmolStr; 7use tt::SmolStr;
8 8
9/// A simple configuration value passed in from the outside.
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub enum CfgAtom {
12 /// eg. `#[cfg(test)]`
13 Flag(SmolStr),
14 /// eg. `#[cfg(target_os = "linux")]`
15 ///
16 /// Note that a key can have multiple values that are all considered "active" at the same time.
17 /// For example, `#[cfg(target_feature = "sse")]` and `#[cfg(target_feature = "sse2")]`.
18 KeyValue { key: SmolStr, value: SmolStr },
19}
20
9#[derive(Debug, Clone, PartialEq, Eq)] 21#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum CfgExpr { 22pub enum CfgExpr {
11 Invalid, 23 Invalid,
12 Atom(SmolStr), 24 Atom(CfgAtom),
13 KeyValue { key: SmolStr, value: SmolStr },
14 All(Vec<CfgExpr>), 25 All(Vec<CfgExpr>),
15 Any(Vec<CfgExpr>), 26 Any(Vec<CfgExpr>),
16 Not(Box<CfgExpr>), 27 Not(Box<CfgExpr>),
17} 28}
18 29
30impl From<CfgAtom> for CfgExpr {
31 fn from(atom: CfgAtom) -> Self {
32 CfgExpr::Atom(atom)
33 }
34}
35
19impl CfgExpr { 36impl CfgExpr {
20 pub fn parse(tt: &tt::Subtree) -> CfgExpr { 37 pub fn parse(tt: &tt::Subtree) -> CfgExpr {
21 next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid) 38 next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
22 } 39 }
23 /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates. 40 /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
24 pub fn fold(&self, query: &dyn Fn(&SmolStr, Option<&SmolStr>) -> bool) -> Option<bool> { 41 pub fn fold(&self, query: &dyn Fn(&CfgAtom) -> bool) -> Option<bool> {
25 match self { 42 match self {
26 CfgExpr::Invalid => None, 43 CfgExpr::Invalid => None,
27 CfgExpr::Atom(name) => Some(query(name, None)), 44 CfgExpr::Atom(atom) => Some(query(atom)),
28 CfgExpr::KeyValue { key, value } => Some(query(key, Some(value))),
29 CfgExpr::All(preds) => { 45 CfgExpr::All(preds) => {
30 preds.iter().try_fold(true, |s, pred| Some(s && pred.fold(query)?)) 46 preds.iter().try_fold(true, |s, pred| Some(s && pred.fold(query)?))
31 } 47 }
@@ -54,7 +70,7 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
54 // FIXME: escape? raw string? 70 // FIXME: escape? raw string?
55 let value = 71 let value =
56 SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"')); 72 SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"'));
57 CfgExpr::KeyValue { key: name, value } 73 CfgAtom::KeyValue { key: name, value }.into()
58 } 74 }
59 _ => return Some(CfgExpr::Invalid), 75 _ => return Some(CfgExpr::Invalid),
60 } 76 }
@@ -70,7 +86,7 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
70 _ => CfgExpr::Invalid, 86 _ => CfgExpr::Invalid,
71 } 87 }
72 } 88 }
73 _ => CfgExpr::Atom(name), 89 _ => CfgAtom::Flag(name).into(),
74 }; 90 };
75 91
76 // Eat comma separator 92 // Eat comma separator
@@ -101,22 +117,22 @@ mod tests {
101 117
102 #[test] 118 #[test]
103 fn test_cfg_expr_parser() { 119 fn test_cfg_expr_parser() {
104 assert_parse_result("#![cfg(foo)]", CfgExpr::Atom("foo".into())); 120 assert_parse_result("#![cfg(foo)]", CfgAtom::Flag("foo".into()).into());
105 assert_parse_result("#![cfg(foo,)]", CfgExpr::Atom("foo".into())); 121 assert_parse_result("#![cfg(foo,)]", CfgAtom::Flag("foo".into()).into());
106 assert_parse_result( 122 assert_parse_result(
107 "#![cfg(not(foo))]", 123 "#![cfg(not(foo))]",
108 CfgExpr::Not(Box::new(CfgExpr::Atom("foo".into()))), 124 CfgExpr::Not(Box::new(CfgAtom::Flag("foo".into()).into())),
109 ); 125 );
110 assert_parse_result("#![cfg(foo(bar))]", CfgExpr::Invalid); 126 assert_parse_result("#![cfg(foo(bar))]", CfgExpr::Invalid);
111 127
112 // Only take the first 128 // Only take the first
113 assert_parse_result(r#"#![cfg(foo, bar = "baz")]"#, CfgExpr::Atom("foo".into())); 129 assert_parse_result(r#"#![cfg(foo, bar = "baz")]"#, CfgAtom::Flag("foo".into()).into());
114 130
115 assert_parse_result( 131 assert_parse_result(
116 r#"#![cfg(all(foo, bar = "baz"))]"#, 132 r#"#![cfg(all(foo, bar = "baz"))]"#,
117 CfgExpr::All(vec![ 133 CfgExpr::All(vec![
118 CfgExpr::Atom("foo".into()), 134 CfgAtom::Flag("foo".into()).into(),
119 CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() }, 135 CfgAtom::KeyValue { key: "bar".into(), value: "baz".into() }.into(),
120 ]), 136 ]),
121 ); 137 );
122 138
@@ -126,7 +142,7 @@ mod tests {
126 CfgExpr::Not(Box::new(CfgExpr::Invalid)), 142 CfgExpr::Not(Box::new(CfgExpr::Invalid)),
127 CfgExpr::All(vec![]), 143 CfgExpr::All(vec![]),
128 CfgExpr::Invalid, 144 CfgExpr::Invalid,
129 CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() }, 145 CfgAtom::KeyValue { key: "bar".into(), value: "baz".into() }.into(),
130 ]), 146 ]),
131 ); 147 );
132 } 148 }