Skip to content

Commit cea8442

Browse files
committed
Allow setting cfgs
1 parent ee8c18c commit cea8442

File tree

8 files changed

+73
-89
lines changed

8 files changed

+73
-89
lines changed

crates/cfg/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl CfgOptions {
8686
}
8787
}
8888

89-
#[derive(Clone, Debug, PartialEq, Eq)]
89+
#[derive(Default, Clone, Debug, PartialEq, Eq)]
9090
pub struct CfgDiff {
9191
// Invariants: No duplicates, no atom that's both in `enable` and `disable`.
9292
enable: Vec<CfgAtom>,

crates/project-model/src/cargo_workspace.rs

+1-38
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! See [`CargoWorkspace`].
22
3-
use std::iter;
43
use std::path::PathBuf;
54
use std::str::from_utf8;
65
use std::{ops, process::Command};
@@ -58,20 +57,6 @@ pub enum RustLibSource {
5857
Discover,
5958
}
6059

61-
/// Crates to disable `#[cfg(test)]` on.
62-
#[derive(Clone, Debug, PartialEq, Eq)]
63-
pub enum UnsetTestCrates {
64-
None,
65-
Only(Vec<String>),
66-
All,
67-
}
68-
69-
impl Default for UnsetTestCrates {
70-
fn default() -> Self {
71-
Self::None
72-
}
73-
}
74-
7560
#[derive(Clone, Debug, PartialEq, Eq)]
7661
pub enum CargoFeatures {
7762
All,
@@ -100,8 +85,7 @@ pub struct CargoConfig {
10085
pub sysroot_src: Option<AbsPathBuf>,
10186
/// rustc private crate source
10287
pub rustc_source: Option<RustLibSource>,
103-
/// crates to disable `#[cfg(test)]` on
104-
pub unset_test_crates: UnsetTestCrates,
88+
pub cfg_overrides: CfgOverrides,
10589
/// Invoke `cargo check` through the RUSTC_WRAPPER.
10690
pub wrap_rustc_in_build_scripts: bool,
10791
/// The command to run instead of `cargo check` for building build scripts.
@@ -114,27 +98,6 @@ pub struct CargoConfig {
11498
pub invocation_location: InvocationLocation,
11599
}
116100

117-
impl CargoConfig {
118-
pub fn cfg_overrides(&self) -> CfgOverrides {
119-
match &self.unset_test_crates {
120-
UnsetTestCrates::None => CfgOverrides::Selective(iter::empty().collect()),
121-
UnsetTestCrates::Only(unset_test_crates) => CfgOverrides::Selective(
122-
unset_test_crates
123-
.iter()
124-
.cloned()
125-
.zip(iter::repeat_with(|| {
126-
cfg::CfgDiff::new(Vec::new(), vec![cfg::CfgAtom::Flag("test".into())])
127-
.unwrap()
128-
}))
129-
.collect(),
130-
),
131-
UnsetTestCrates::All => CfgOverrides::Wildcard(
132-
cfg::CfgDiff::new(Vec::new(), vec![cfg::CfgAtom::Flag("test".into())]).unwrap(),
133-
),
134-
}
135-
}
136-
}
137-
138101
pub type Package = Idx<PackageData>;
139102

140103
pub type Target = Idx<TargetData>;

crates/project-model/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub use crate::{
4444
build_scripts::WorkspaceBuildScripts,
4545
cargo_workspace::{
4646
CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency,
47-
RustLibSource, Target, TargetData, TargetKind, UnsetTestCrates,
47+
RustLibSource, Target, TargetData, TargetKind,
4848
},
4949
manifest_path::ManifestPath,
5050
project_json::{ProjectJson, ProjectJsonData},

crates/project-model/src/tests.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,10 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
158158

159159
#[test]
160160
fn cargo_hello_world_project_model_with_wildcard_overrides() {
161-
let cfg_overrides = CfgOverrides::Wildcard(
162-
CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
163-
);
161+
let cfg_overrides = CfgOverrides {
162+
global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
163+
selective: Default::default(),
164+
};
164165
let (crate_graph, _proc_macros) =
165166
load_cargo_with_overrides("hello-world-metadata.json", cfg_overrides);
166167
check_crate_graph(
@@ -173,14 +174,13 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
173174

174175
#[test]
175176
fn cargo_hello_world_project_model_with_selective_overrides() {
176-
let cfg_overrides = {
177-
CfgOverrides::Selective(
178-
std::iter::once((
179-
"libc".to_owned(),
180-
CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
181-
))
182-
.collect(),
183-
)
177+
let cfg_overrides = CfgOverrides {
178+
global: Default::default(),
179+
selective: std::iter::once((
180+
"libc".to_owned(),
181+
CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(),
182+
))
183+
.collect(),
184184
};
185185
let (crate_graph, _proc_macros) =
186186
load_cargo_with_overrides("hello-world-metadata.json", cfg_overrides);

crates/project-model/src/workspace.rs

+15-33
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,17 @@ use crate::{
2828
};
2929

3030
/// A set of cfg-overrides per crate.
31-
///
32-
/// `Wildcard(..)` is useful e.g. disabling `#[cfg(test)]` on all crates,
33-
/// without having to first obtain a list of all crates.
34-
#[derive(Debug, Clone, Eq, PartialEq)]
35-
pub enum CfgOverrides {
36-
/// A single global set of overrides matching all crates.
37-
Wildcard(CfgDiff),
31+
#[derive(Default, Debug, Clone, Eq, PartialEq)]
32+
pub struct CfgOverrides {
33+
/// A global set of overrides matching all crates.
34+
pub global: CfgDiff,
3835
/// A set of overrides matching specific crates.
39-
Selective(FxHashMap<String, CfgDiff>),
40-
}
41-
42-
impl Default for CfgOverrides {
43-
fn default() -> Self {
44-
Self::Selective(FxHashMap::default())
45-
}
36+
pub selective: FxHashMap<String, CfgDiff>,
4637
}
4738

4839
impl CfgOverrides {
4940
pub fn len(&self) -> usize {
50-
match self {
51-
CfgOverrides::Wildcard(_) => 1,
52-
CfgOverrides::Selective(hash_map) => hash_map.len(),
53-
}
41+
self.global.len() + self.selective.iter().map(|(_, it)| it.len()).sum::<usize>()
5442
}
5543
}
5644

@@ -292,7 +280,7 @@ impl ProjectWorkspace {
292280
let rustc_cfg =
293281
rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), &config.extra_env);
294282

295-
let cfg_overrides = config.cfg_overrides();
283+
let cfg_overrides = config.cfg_overrides.clone();
296284
let data_layout = target_data_layout::get(
297285
Some(&cargo_toml),
298286
config.target.as_deref(),
@@ -886,20 +874,18 @@ fn cargo_to_crate_graph(
886874
cfg_options.insert_atom("test".into());
887875
}
888876

889-
let overrides = match override_cfg {
890-
CfgOverrides::Wildcard(cfg_diff) => Some(cfg_diff),
891-
CfgOverrides::Selective(cfg_overrides) => cfg_overrides.get(&cargo[pkg].name),
877+
if !override_cfg.global.is_empty() {
878+
cfg_options.apply_diff(override_cfg.global.clone());
892879
};
893-
894-
if let Some(overrides) = overrides {
880+
if let Some(diff) = override_cfg.selective.get(&cargo[pkg].name) {
895881
// FIXME: this is sort of a hack to deal with #![cfg(not(test))] vanishing such as seen
896882
// in ed25519_dalek (#7243), and libcore (#9203) (although you only hit that one while
897883
// working on rust-lang/rust as that's the only time it appears outside sysroot).
898884
//
899885
// A more ideal solution might be to reanalyze crates based on where the cursor is and
900886
// figure out the set of cfgs that would have to apply to make it active.
901887

902-
cfg_options.apply_diff(overrides.clone());
888+
cfg_options.apply_diff(diff.clone());
903889
};
904890
cfg_options
905891
});
@@ -1109,22 +1095,18 @@ fn handle_rustc_crates(
11091095

11101096
let mut cfg_options = cfg_options.clone();
11111097

1112-
let overrides = match override_cfg {
1113-
CfgOverrides::Wildcard(cfg_diff) => Some(cfg_diff),
1114-
CfgOverrides::Selective(cfg_overrides) => {
1115-
cfg_overrides.get(&rustc_workspace[pkg].name)
1116-
}
1098+
if !override_cfg.global.is_empty() {
1099+
cfg_options.apply_diff(override_cfg.global.clone());
11171100
};
1118-
1119-
if let Some(overrides) = overrides {
1101+
if let Some(diff) = override_cfg.selective.get(&rustc_workspace[pkg].name) {
11201102
// FIXME: this is sort of a hack to deal with #![cfg(not(test))] vanishing such as seen
11211103
// in ed25519_dalek (#7243), and libcore (#9203) (although you only hit that one while
11221104
// working on rust-lang/rust as that's the only time it appears outside sysroot).
11231105
//
11241106
// A more ideal solution might be to reanalyze crates based on where the cursor is and
11251107
// figure out the set of cfgs that would have to apply to make it active.
11261108

1127-
cfg_options.apply_diff(overrides.clone());
1109+
cfg_options.apply_diff(diff.clone());
11281110
};
11291111

11301112
for &tgt in rustc_workspace[pkg].targets.iter() {

crates/rust-analyzer/src/config.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
1010
use std::{fmt, iter, ops::Not, path::PathBuf};
1111

12+
use cfg::{CfgAtom, CfgDiff};
1213
use flycheck::FlycheckConfig;
1314
use ide::{
1415
AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
@@ -23,7 +24,6 @@ use itertools::Itertools;
2324
use lsp_types::{ClientCapabilities, MarkupKind};
2425
use project_model::{
2526
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource,
26-
UnsetTestCrates,
2727
};
2828
use rustc_hash::{FxHashMap, FxHashSet};
2929
use serde::{de::DeserializeOwned, Deserialize};
@@ -101,6 +101,8 @@ config_data! {
101101
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
102102
/// avoid checking unnecessary things.
103103
cargo_buildScripts_useRustcWrapper: bool = "true",
104+
/// List of cfg options to enable with the given values.
105+
cargo_cfgs: FxHashMap<String, String> = "{}",
104106
/// Extra arguments that are passed to every cargo invocation.
105107
cargo_extraArgs: Vec<String> = "[]",
106108
/// Extra environment variables that will be set when running cargo, rustc
@@ -128,7 +130,7 @@ config_data! {
128130
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
129131
// than `checkOnSave_target`
130132
cargo_target: Option<String> = "null",
131-
/// Unsets `#[cfg(test)]` for the specified crates.
133+
/// Unsets the implicit `#[cfg(test)]` for the specified crates.
132134
cargo_unsetTest: Vec<String> = "[\"core\"]",
133135

134136
/// Run the check command for diagnostics on save.
@@ -1189,7 +1191,34 @@ impl Config {
11891191
sysroot,
11901192
sysroot_src,
11911193
rustc_source,
1192-
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
1194+
cfg_overrides: project_model::CfgOverrides {
1195+
global: CfgDiff::new(
1196+
self.data
1197+
.cargo_cfgs
1198+
.iter()
1199+
.map(|(key, val)| {
1200+
if val.is_empty() {
1201+
CfgAtom::Flag(key.into())
1202+
} else {
1203+
CfgAtom::KeyValue { key: key.into(), value: val.into() }
1204+
}
1205+
})
1206+
.collect(),
1207+
vec![],
1208+
)
1209+
.unwrap(),
1210+
selective: self
1211+
.data
1212+
.cargo_unsetTest
1213+
.iter()
1214+
.map(|it| {
1215+
(
1216+
it.clone(),
1217+
CfgDiff::new(vec![], vec![CfgAtom::Flag("test".into())]).unwrap(),
1218+
)
1219+
})
1220+
.collect(),
1221+
},
11931222
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,
11941223
invocation_strategy: match self.data.cargo_buildScripts_invocationStrategy {
11951224
InvocationStrategy::Once => project_model::InvocationStrategy::Once,

docs/user/generated_config.adoc

+6-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ cargo check --quiet --workspace --message-format=json --all-targets
7171
Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
7272
avoid checking unnecessary things.
7373
--
74+
[[rust-analyzer.cargo.cfgs]]rust-analyzer.cargo.cfgs (default: `{}`)::
75+
+
76+
--
77+
List of cfg options to enable with the given values.
78+
--
7479
[[rust-analyzer.cargo.extraArgs]]rust-analyzer.cargo.extraArgs (default: `[]`)::
7580
+
7681
--
@@ -120,7 +125,7 @@ Compilation target override (target triple).
120125
[[rust-analyzer.cargo.unsetTest]]rust-analyzer.cargo.unsetTest (default: `["core"]`)::
121126
+
122127
--
123-
Unsets `#[cfg(test)]` for the specified crates.
128+
Unsets the implicit `#[cfg(test)]` for the specified crates.
124129
--
125130
[[rust-analyzer.checkOnSave]]rust-analyzer.checkOnSave (default: `true`)::
126131
+

editors/code/package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@
553553
"default": true,
554554
"type": "boolean"
555555
},
556+
"rust-analyzer.cargo.cfgs": {
557+
"markdownDescription": "List of cfg options to enable with the given values.",
558+
"default": {},
559+
"type": "object"
560+
},
556561
"rust-analyzer.cargo.extraArgs": {
557562
"markdownDescription": "Extra arguments that are passed to every cargo invocation.",
558563
"default": [],
@@ -617,7 +622,7 @@
617622
]
618623
},
619624
"rust-analyzer.cargo.unsetTest": {
620-
"markdownDescription": "Unsets `#[cfg(test)]` for the specified crates.",
625+
"markdownDescription": "Unsets the implicit `#[cfg(test)]` for the specified crates.",
621626
"default": [
622627
"core"
623628
],

0 commit comments

Comments
 (0)