about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-23 10:01:35 +0000
committerbors <bors@rust-lang.org>2024-08-23 10:01:35 +0000
commit3a097e16594f0f1aa89ff23a3f4f4659c09d9052 (patch)
tree6ccf96e4fd8b7b4db951d9cedaf1f207e2ef8a8a
parente030cf01ba0b88325c02dbfb46f826a6248dbbc3 (diff)
parentaa6e8d3db553721eed97d5b6afc64d44eb9f8a2b (diff)
downloadrust-3a097e16594f0f1aa89ff23a3f4f4659c09d9052.tar.gz
rust-3a097e16594f0f1aa89ff23a3f4f4659c09d9052.zip
Auto merge of #17857 - ChayimFriedman2:rust-project-cfg-group, r=Veykril
feat: Allow declaring cfg groups in rust-project.json, to help sharing common cfgs

Closes #17815.
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs34
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/cfg-groups.json26
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt545
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc12
5 files changed, 619 insertions, 4 deletions
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 7dea0c38398..a09c7a77abc 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index e3bc81e1963..8c0b4755849 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/test_data/cfg-groups.json b/src/tools/rust-analyzer/crates/project-model/test_data/cfg-groups.json
new file mode 100644
index 00000000000..29f83afd9d4
--- /dev/null
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
new file mode 100644
index 00000000000..8261e5a2d90
--- /dev/null
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 703ec66921c..246ebdab2c9 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/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[];