From 43f09ad36ccc1c53c78a66274693e53161c9b2fa Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Thu, 3 Oct 2019 01:20:08 +0800 Subject: [PATCH] Refactor CfgOptions inside --- crates/ra_cfg/src/lib.rs | 26 +++++++++++++++++--------- crates/ra_hir/src/nameres/tests.rs | 6 +++--- crates/ra_ide_api/src/mock_analysis.rs | 1 - 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs index fa5822d8a6..dd81a73f48 100644 --- a/crates/ra_cfg/src/lib.rs +++ b/crates/ra_cfg/src/lib.rs @@ -1,24 +1,32 @@ //! ra_cfg defines conditional compiling options, `cfg` attibute parser and evaluator use ra_syntax::SmolStr; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashSet; mod cfg_expr; pub use cfg_expr::{parse_cfg, CfgExpr}; +/// Configuration options used for conditional compilition on items with `cfg` attributes. +/// We have two kind of options in different namespaces: atomic options like `unix`, and +/// key-value options like `target_arch="x86"`. +/// +/// Note that for key-value options, one key can have multiple values (but not none). +/// `feature` is an example. We have both `feature="foo"` and `feature="bar"` if features +/// `foo` and `bar` are both enabled. And here, we store key-value options as a set of tuple +/// of key and value in `key_values`. +/// +/// See: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct CfgOptions { atoms: FxHashSet, - features: FxHashSet, - options: FxHashMap, + key_values: FxHashSet<(SmolStr, SmolStr)>, } impl CfgOptions { pub fn check(&self, cfg: &CfgExpr) -> Option { cfg.fold(&|key, value| match value { None => self.atoms.contains(key), - Some(value) if key == "feature" => self.features.contains(value), - Some(value) => self.options.get(key).map_or(false, |v| v == value), + Some(value) => self.key_values.contains(&(key.clone(), value.clone())), }) } @@ -31,13 +39,13 @@ impl CfgOptions { self } - pub fn feature(mut self, name: SmolStr) -> CfgOptions { - self.features.insert(name); + pub fn key_value(mut self, key: SmolStr, value: SmolStr) -> CfgOptions { + self.key_values.insert((key, value)); self } - pub fn option(mut self, key: SmolStr, value: SmolStr) -> CfgOptions { - self.options.insert(key, value); + pub fn remove_atom(mut self, name: &SmolStr) -> CfgOptions { + self.atoms.remove(name); self } } diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index f43767e595..34dd795743 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -563,9 +563,9 @@ fn cfg_test() { "main": ("/main.rs", ["std"]), "std": ("/lib.rs", [], CfgOptions::default() .atom("test".into()) - .feature("foo".into()) - .feature("bar".into()) - .option("opt".into(), "42".into()) + .key_value("feature".into(), "foo".into()) + .key_value("feature".into(), "bar".into()) + .key_value("opt".into(), "42".into()) ), }, ); diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 13258b63dd..80b71894cd 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs @@ -94,7 +94,6 @@ impl MockAnalysis { assert!(path.starts_with('/')); let path = RelativePathBuf::from_path(&path[1..]).unwrap(); let file_id = FileId(i as u32 + 1); - // FIXME: cfg options let cfg_options = CfgOptions::default(); if path == "/lib.rs" || path == "/main.rs" { root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options));