Begin transition to new fields for JsonProject crate cfgs

This starts the transition to a new method of documenting the cfgs that are
enabled for a given crate in the json file.  This is changing from a list
of atoms and a dict of key:value pairs, to a list of strings that is
equivalent to that returned by `rustc --print cfg ..`, and parsed in the
same manner by rust-analyzer.

This is the first of two changes, which adds the new field that contains
the list of strings.  Next change will complete the transition and remove
the previous fields.
This commit is contained in:
Aaron Wood 2020-05-08 16:59:52 -07:00
parent a5f2b16366
commit beb79ed104
3 changed files with 92 additions and 2 deletions

View file

@ -20,8 +20,17 @@ pub struct Crate {
pub(crate) root_module: PathBuf,
pub(crate) edition: Edition,
pub(crate) deps: Vec<Dep>,
// This is the preferred method of providing cfg options.
#[serde(default)]
pub(crate) cfg: FxHashSet<String>,
// These two are here for transition only.
#[serde(default)]
pub(crate) atom_cfgs: FxHashSet<String>,
#[serde(default)]
pub(crate) key_value_cfgs: FxHashMap<String, String>,
pub(crate) out_dir: Option<PathBuf>,
pub(crate) proc_macro_dylib_path: Option<PathBuf>,
}
@ -54,3 +63,73 @@ pub struct JsonProject {
pub(crate) roots: Vec<Root>,
pub(crate) crates: Vec<Crate>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_crate_deserialization() {
let raw_json = json!( {
"crate_id": 2,
"root_module": "this/is/a/file/path.rs",
"deps": [
{
"crate": 1,
"name": "some_dep_crate"
},
],
"edition": "2015",
"cfg": [
"atom_1",
"atom_2",
"feature=feature_1",
"feature=feature_2",
"other=value",
],
});
let krate: Crate = serde_json::from_value(raw_json).unwrap();
assert!(krate.cfg.contains(&"atom_1".to_string()));
assert!(krate.cfg.contains(&"atom_2".to_string()));
assert!(krate.cfg.contains(&"feature=feature_1".to_string()));
assert!(krate.cfg.contains(&"feature=feature_2".to_string()));
assert!(krate.cfg.contains(&"other=value".to_string()));
}
#[test]
fn test_crate_deserialization_old_json() {
let raw_json = json!( {
"crate_id": 2,
"root_module": "this/is/a/file/path.rs",
"deps": [
{
"crate": 1,
"name": "some_dep_crate"
},
],
"edition": "2015",
"atom_cfgs": [
"atom_1",
"atom_2",
],
"key_value_cfgs": {
"feature": "feature_1",
"feature": "feature_2",
"other": "value",
},
});
let krate: Crate = serde_json::from_value(raw_json).unwrap();
assert!(krate.atom_cfgs.contains(&"atom_1".to_string()));
assert!(krate.atom_cfgs.contains(&"atom_2".to_string()));
assert!(krate.key_value_cfgs.contains_key(&"feature".to_string()));
assert_eq!(krate.key_value_cfgs.get("feature"), Some(&"feature_2".to_string()));
assert!(krate.key_value_cfgs.contains_key(&"other".to_string()));
assert_eq!(krate.key_value_cfgs.get("other"), Some(&"value".to_string()));
}
}

View file

@ -273,6 +273,16 @@ impl ProjectWorkspace {
};
let cfg_options = {
let mut opts = default_cfg_options.clone();
for cfg in &krate.cfg {
match cfg.find('=') {
None => opts.insert_atom(cfg.into()),
Some(pos) => {
let key = &cfg[..pos];
let value = cfg[pos + 1..].trim_matches('"');
opts.insert_key_value(key.into(), value.into());
}
}
}
for name in &krate.atom_cfgs {
opts.insert_atom(name.into());
}

View file

@ -384,8 +384,9 @@ fn test_missing_module_code_action_in_json_project() {
"root_module": path.join("src/lib.rs"),
"deps": [],
"edition": "2015",
"atom_cfgs": [],
"key_value_cfgs": {}
"cfg": [ "cfg_atom_1", "feature=cfg_1"],
"atom_cfgs": ["atom_2"],
"key_value_cfgs": { "feature": "key_value_feature", "other": "value"}
} ]
});