Skip to content

Commit 8df105b

Browse files
bors[bot]matklad
andauthored
Merge #5505
5505: Cleanup CFG API r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2 parents 7bada8a + 38e38d9 commit 8df105b

File tree

6 files changed

+44
-67
lines changed

6 files changed

+44
-67
lines changed

crates/ra_cfg/src/cfg_expr.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use std::slice::Iter as SliceIter;
66

77
use ra_syntax::SmolStr;
8-
use tt::{Leaf, Subtree, TokenTree};
98

109
#[derive(Debug, Clone, PartialEq, Eq)]
1110
pub enum CfgExpr {
@@ -18,6 +17,9 @@ pub enum CfgExpr {
1817
}
1918

2019
impl CfgExpr {
20+
pub fn parse(tt: &tt::Subtree) -> CfgExpr {
21+
next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
22+
}
2123
/// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
2224
pub fn fold(&self, query: &dyn Fn(&SmolStr, Option<&SmolStr>) -> bool) -> Option<bool> {
2325
match self {
@@ -35,22 +37,18 @@ impl CfgExpr {
3537
}
3638
}
3739

38-
pub fn parse_cfg(tt: &Subtree) -> CfgExpr {
39-
next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
40-
}
41-
4240
fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
4341
let name = match it.next() {
4442
None => return None,
45-
Some(TokenTree::Leaf(Leaf::Ident(ident))) => ident.text.clone(),
43+
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.text.clone(),
4644
Some(_) => return Some(CfgExpr::Invalid),
4745
};
4846

4947
// Peek
5048
let ret = match it.as_slice().first() {
51-
Some(TokenTree::Leaf(Leaf::Punct(punct))) if punct.char == '=' => {
49+
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
5250
match it.as_slice().get(1) {
53-
Some(TokenTree::Leaf(Leaf::Literal(literal))) => {
51+
Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => {
5452
it.next();
5553
it.next();
5654
// FIXME: escape? raw string?
@@ -61,7 +59,7 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
6159
_ => return Some(CfgExpr::Invalid),
6260
}
6361
}
64-
Some(TokenTree::Subtree(subtree)) => {
62+
Some(tt::TokenTree::Subtree(subtree)) => {
6563
it.next();
6664
let mut sub_it = subtree.token_trees.iter();
6765
let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it)).collect();
@@ -76,7 +74,7 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
7674
};
7775

7876
// Eat comma separator
79-
if let Some(TokenTree::Leaf(Leaf::Punct(punct))) = it.as_slice().first() {
77+
if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = it.as_slice().first() {
8078
if punct.char == ',' {
8179
it.next();
8280
}
@@ -99,7 +97,8 @@ mod tests {
9997

10098
fn assert_parse_result(input: &str, expected: CfgExpr) {
10199
let (tt, _) = get_token_tree_generated(input);
102-
assert_eq!(parse_cfg(&tt), expected);
100+
let cfg = CfgExpr::parse(&tt);
101+
assert_eq!(cfg, expected);
103102
}
104103

105104
#[test]

crates/ra_cfg/src/lib.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod cfg_expr;
55
use ra_syntax::SmolStr;
66
use rustc_hash::FxHashSet;
77

8-
pub use cfg_expr::{parse_cfg, CfgExpr};
8+
pub use cfg_expr::CfgExpr;
99

1010
/// Configuration options used for conditional compilition on items with `cfg` attributes.
1111
/// We have two kind of options in different namespaces: atomic options like `unix`, and
@@ -31,18 +31,10 @@ impl CfgOptions {
3131
})
3232
}
3333

34-
pub fn is_cfg_enabled(&self, attr: &tt::Subtree) -> Option<bool> {
35-
self.check(&parse_cfg(attr))
36-
}
37-
3834
pub fn insert_atom(&mut self, key: SmolStr) {
3935
self.atoms.insert(key);
4036
}
4137

42-
pub fn remove_atom(&mut self, name: &str) {
43-
self.atoms.remove(name);
44-
}
45-
4638
pub fn insert_key_value(&mut self, key: SmolStr, value: SmolStr) {
4739
self.key_values.insert((key, value));
4840
}

crates/ra_hir_def/src/attr.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{ops, sync::Arc};
55
use either::Either;
66
use hir_expand::{hygiene::Hygiene, AstId, InFile};
77
use mbe::ast_to_token_tree;
8-
use ra_cfg::CfgOptions;
8+
use ra_cfg::{CfgExpr, CfgOptions};
99
use ra_syntax::{
1010
ast::{self, AstNode, AttrsOwner},
1111
SmolStr,
@@ -125,9 +125,12 @@ impl Attrs {
125125
AttrQuery { attrs: self, key }
126126
}
127127

128-
pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
128+
pub fn cfg(&self) -> impl Iterator<Item = CfgExpr> + '_ {
129129
// FIXME: handle cfg_attr :-)
130-
self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
130+
self.by_key("cfg").tt_values().map(CfgExpr::parse)
131+
}
132+
pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
133+
self.cfg().all(|cfg| cfg_options.check(&cfg) != Some(false))
131134
}
132135
}
133136

crates/ra_ide/src/runnables.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ fn runnable_fn(
168168
};
169169

170170
let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def));
171-
let cfg_exprs =
172-
attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
171+
let cfg_exprs = attrs.cfg().collect();
173172

174173
let nav = if let RunnableKind::DocTest { .. } = kind {
175174
NavigationTarget::from_doc_commented(
@@ -242,9 +241,7 @@ fn runnable_mod(
242241
.join("::");
243242

244243
let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module));
245-
let cfg_exprs =
246-
attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
247-
244+
let cfg_exprs = attrs.cfg().collect();
248245
let nav = module_def.to_nav(sema.db);
249246
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs })
250247
}

crates/ra_project_model/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use paths::{AbsPath, AbsPathBuf};
1515
use ra_cfg::CfgOptions;
1616
use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId};
1717
use rustc_hash::{FxHashMap, FxHashSet};
18+
use stdx::split_delim;
1819

1920
pub use crate::{
2021
cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind},
@@ -529,11 +530,10 @@ fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions {
529530
match rustc_cfgs {
530531
Ok(rustc_cfgs) => {
531532
for line in rustc_cfgs.lines() {
532-
match line.find('=') {
533+
match split_delim(line, '=') {
533534
None => cfg_options.insert_atom(line.into()),
534-
Some(pos) => {
535-
let key = &line[..pos];
536-
let value = line[pos + 1..].trim_matches('"');
535+
Some((key, value)) => {
536+
let value = value.trim_matches('"');
537537
cfg_options.insert_key_value(key.into(), value.into());
538538
}
539539
}

crates/rust-analyzer/src/cargo_target_spec.rs

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -177,49 +177,35 @@ fn required_features(cfg_expr: &CfgExpr, features: &mut Vec<String>) {
177177
mod tests {
178178
use super::*;
179179

180-
use mbe::{ast_to_token_tree, TokenMap};
181-
use ra_cfg::parse_cfg;
180+
use mbe::ast_to_token_tree;
181+
use ra_cfg::CfgExpr;
182182
use ra_syntax::{
183183
ast::{self, AstNode},
184184
SmolStr,
185185
};
186186

187-
fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) {
188-
let source_file = ast::SourceFile::parse(input).ok().unwrap();
189-
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
190-
ast_to_token_tree(&tt).unwrap()
191-
}
192-
193-
#[test]
194-
fn test_cfg_expr_minimal_features_needed() {
195-
let (subtree, _) = get_token_tree_generated(r#"#![cfg(feature = "baz")]"#);
196-
let cfg_expr = parse_cfg(&subtree);
197-
let mut min_features = vec![];
198-
required_features(&cfg_expr, &mut min_features);
199-
200-
assert_eq!(min_features, vec![SmolStr::new("baz")]);
201-
202-
let (subtree, _) =
203-
get_token_tree_generated(r#"#![cfg(all(feature = "baz", feature = "foo"))]"#);
204-
let cfg_expr = parse_cfg(&subtree);
205-
206-
let mut min_features = vec![];
207-
required_features(&cfg_expr, &mut min_features);
208-
assert_eq!(min_features, vec![SmolStr::new("baz"), SmolStr::new("foo")]);
187+
fn check(cfg: &str, expected_features: &[&str]) {
188+
let cfg_expr = {
189+
let source_file = ast::SourceFile::parse(cfg).ok().unwrap();
190+
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
191+
let (tt, _) = ast_to_token_tree(&tt).unwrap();
192+
CfgExpr::parse(&tt)
193+
};
209194

210-
let (subtree, _) =
211-
get_token_tree_generated(r#"#![cfg(any(feature = "baz", feature = "foo", unix))]"#);
212-
let cfg_expr = parse_cfg(&subtree);
195+
let mut features = vec![];
196+
required_features(&cfg_expr, &mut features);
213197

214-
let mut min_features = vec![];
215-
required_features(&cfg_expr, &mut min_features);
216-
assert_eq!(min_features, vec![SmolStr::new("baz")]);
198+
let expected_features =
199+
expected_features.iter().map(|&it| SmolStr::new(it)).collect::<Vec<_>>();
217200

218-
let (subtree, _) = get_token_tree_generated(r#"#![cfg(foo)]"#);
219-
let cfg_expr = parse_cfg(&subtree);
201+
assert_eq!(features, expected_features);
202+
}
220203

221-
let mut min_features = vec![];
222-
required_features(&cfg_expr, &mut min_features);
223-
assert!(min_features.is_empty());
204+
#[test]
205+
fn test_cfg_expr_minimal_features_needed() {
206+
check(r#"#![cfg(feature = "baz")]"#, &["baz"]);
207+
check(r#"#![cfg(all(feature = "baz", feature = "foo"))]"#, &["baz", "foo"]);
208+
check(r#"#![cfg(any(feature = "baz", feature = "foo", unix))]"#, &["baz"]);
209+
check(r#"#![cfg(foo)]"#, &[]);
224210
}
225211
}

0 commit comments

Comments
 (0)