Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/project-model/src/project_json.rs34
-rw-r--r--crates/project-model/src/tests.rs6
-rw-r--r--crates/project-model/test_data/cfg-groups.json26
-rw-r--r--crates/project-model/test_data/output/rust_project_cfg_groups.txt545
-rw-r--r--docs/user/manual.adoc12
5 files changed, 619 insertions, 4 deletions
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index 7dea0c3839..a09c7a77ab 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -52,7 +52,7 @@
use base_db::{CrateDisplayName, CrateName};
use cfg::CfgAtom;
use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
-use rustc_hash::FxHashMap;
+use rustc_hash::{FxHashMap, FxHashSet};
use serde::{de, Deserialize, Serialize};
use span::Edition;
@@ -122,6 +122,25 @@ impl ProjectJson {
None => None,
};
+ let cfg = crate_data
+ .cfg_groups
+ .iter()
+ .flat_map(|cfg_extend| {
+ let cfg_group = data.cfg_groups.get(cfg_extend);
+ match cfg_group {
+ Some(cfg_group) => cfg_group.0.iter().cloned(),
+ None => {
+ tracing::error!(
+ "Unknown cfg group `{cfg_extend}` in crate `{}`",
+ crate_data.display_name.as_deref().unwrap_or("<unknown>"),
+ );
+ [].iter().cloned()
+ }
+ }
+ })
+ .chain(crate_data.cfg.0)
+ .collect();
+
Crate {
display_name: crate_data
.display_name
@@ -131,7 +150,7 @@ impl ProjectJson {
edition: crate_data.edition.into(),
version: crate_data.version.as_ref().map(ToString::to_string),
deps: crate_data.deps,
- cfg: crate_data.cfg,
+ cfg,
target: crate_data.target,
env: crate_data.env,
proc_macro_dylib_path: crate_data
@@ -306,11 +325,17 @@ pub enum RunnableKind {
pub struct ProjectJsonData {
sysroot: Option<Utf8PathBuf>,
sysroot_src: Option<Utf8PathBuf>,
+ #[serde(default)]
+ cfg_groups: FxHashMap<String, CfgList>,
crates: Vec<CrateData>,
#[serde(default)]
runnables: Vec<RunnableData>,
}
+#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Default)]
+#[serde(transparent)]
+struct CfgList(#[serde(with = "cfg_")] Vec<CfgAtom>);
+
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
struct CrateData {
display_name: Option<String>,
@@ -320,8 +345,9 @@ struct CrateData {
version: Option<semver::Version>,
deps: Vec<Dep>,
#[serde(default)]
- #[serde(with = "cfg_")]
- cfg: Vec<CfgAtom>,
+ cfg_groups: FxHashSet<String>,
+ #[serde(default)]
+ cfg: CfgList,
target: Option<String>,
#[serde(default)]
env: FxHashMap<String, String>,
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index e3bc81e196..8c0b475584 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -234,6 +234,12 @@ fn rust_project_hello_world_project_model() {
}
#[test]
+fn rust_project_cfg_groups() {
+ let (crate_graph, _proc_macros) = load_rust_project("cfg-groups.json");
+ check_crate_graph(crate_graph, expect_file!["../test_data/output/rust_project_cfg_groups.txt"]);
+}
+
+#[test]
fn rust_project_is_proc_macro_has_proc_macro_dep() {
let (crate_graph, _proc_macros) = load_rust_project("is-proc-macro-project.json");
// Since the project only defines one crate (outside the sysroot crates),
diff --git a/crates/project-model/test_data/cfg-groups.json b/crates/project-model/test_data/cfg-groups.json
new file mode 100644
index 0000000000..29f83afd9d
--- /dev/null
+++ b/crates/project-model/test_data/cfg-groups.json
@@ -0,0 +1,26 @@
+{
+ "sysroot_src": null,
+ "cfg_groups": {
+ "group1": ["group1_cfg=\"some_config\"", "group1_other_cfg=\"other_config\""],
+ "group2": ["group2_cfg=\"yet_another_config\""]
+ },
+ "crates": [
+ {
+ "display_name": "hello_world",
+ "root_module": "$ROOT$src/lib.rs",
+ "edition": "2018",
+ "cfg_groups": ["group1", "group2"],
+ "deps": [],
+ "is_workspace_member": true
+ },
+ {
+ "display_name": "other_crate",
+ "root_module": "$ROOT$src/lib.rs",
+ "edition": "2018",
+ "cfg_groups": ["group2"],
+ "cfg": ["group2_cfg=\"fourth_config\"", "unrelated_cfg"],
+ "deps": [],
+ "is_workspace_member": true
+ }
+ ]
+}
diff --git a/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
new file mode 100644
index 0000000000..8261e5a2d9
--- /dev/null
+++ b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
@@ -0,0 +1,545 @@
+{
+ 0: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "alloc",
+ ),
+ canonical_name: "alloc",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateData>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Alloc,
+ ),
+ is_proc_macro: false,
+ },
+ 1: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "core",
+ ),
+ canonical_name: "core",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Core,
+ ),
+ is_proc_macro: false,
+ },
+ 2: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_abort",
+ ),
+ canonical_name: "panic_abort",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ },
+ 3: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_unwind",
+ ),
+ canonical_name: "panic_unwind",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ },
+ 4: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "proc_macro",
+ ),
+ canonical_name: "proc_macro",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateData>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ ProcMacro,
+ ),
+ is_proc_macro: false,
+ },
+ 5: CrateData {
+ root_file_id: FileId(
+ 6,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "profiler_builtins",
+ ),
+ canonical_name: "profiler_builtins",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ },
+ 6: CrateData {
+ root_file_id: FileId(
+ 7,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std",
+ ),
+ canonical_name: "std",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateData>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(3),
+ name: CrateName(
+ "panic_unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(2),
+ name: CrateName(
+ "panic_abort",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(5),
+ name: CrateName(
+ "profiler_builtins",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(9),
+ name: CrateName(
+ "unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(7),
+ name: CrateName(
+ "std_detect",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Std,
+ ),
+ is_proc_macro: false,
+ },
+ 7: CrateData {
+ root_file_id: FileId(
+ 8,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std_detect",
+ ),
+ canonical_name: "std_detect",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ },
+ 8: CrateData {
+ root_file_id: FileId(
+ 9,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "test",
+ ),
+ canonical_name: "test",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Test,
+ ),
+ is_proc_macro: false,
+ },
+ 9: CrateData {
+ root_file_id: FileId(
+ 10,
+ ),
+ edition: Edition2021,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "unwind",
+ ),
+ canonical_name: "unwind",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "debug_assertions",
+ "miri",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ },
+ 10: CrateData {
+ root_file_id: FileId(
+ 11,
+ ),
+ edition: Edition2018,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello_world",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "group1_cfg=some_config",
+ "group1_other_cfg=other_config",
+ "group2_cfg=yet_another_config",
+ "rust_analyzer",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateData>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(4),
+ name: CrateName(
+ "proc_macro",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello_world",
+ ),
+ },
+ is_proc_macro: false,
+ },
+ 11: CrateData {
+ root_file_id: FileId(
+ 12,
+ ),
+ edition: Edition2018,
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "other_crate",
+ ),
+ canonical_name: "other_crate",
+ },
+ ),
+ cfg_options: CfgOptions(
+ [
+ "group2_cfg=fourth_config",
+ "group2_cfg=yet_another_config",
+ "rust_analyzer",
+ "unrelated_cfg",
+ ],
+ ),
+ potential_cfg_options: None,
+ env: Env {
+ entries: {},
+ },
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateData>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateData>(4),
+ name: CrateName(
+ "proc_macro",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "other_crate",
+ ),
+ },
+ is_proc_macro: false,
+ },
+} \ No newline at end of file
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 703ec66921..246ebdab2c 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -705,6 +705,12 @@ interface JsonProject {
/// several different "sysroots" in one graph of
/// crates.
sysroot_src?: string;
+ /// List of groups of common cfg values, to allow
+ /// sharing them between crates.
+ ///
+ /// Maps from group name to its cfgs. Cfg follow
+ /// the same format as `Crate.cfg`.
+ cfg_groups?: { [key: string]: string[]; };
/// The set of crates comprising the current
/// project. Must include all transitive
/// dependencies as well as sysroot crate (libstd,
@@ -754,6 +760,12 @@ interface Crate {
include_dirs: string[],
exclude_dirs: string[],
},
+ /// List of cfg groups this crate inherits.
+ ///
+ /// All cfg in these groups will be concatenated to
+ /// `cfg`. It is impossible to replace a value from
+ /// the groups.
+ cfg_groups?: string[];
/// The set of cfgs activated for a given crate, like
/// `["unix", "feature=\"foo\"", "feature=\"bar\""]`.
cfg: string[];