mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Allow unsetting default cfgs
This commit is contained in:
parent
505b52da5f
commit
5e18ad0770
@ -18,6 +18,25 @@ pub enum CfgAtom {
|
|||||||
KeyValue { key: Symbol, value: Symbol },
|
KeyValue { key: Symbol, value: Symbol },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for CfgAtom {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for CfgAtom {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()),
|
||||||
|
(CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less,
|
||||||
|
(CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater,
|
||||||
|
(CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => {
|
||||||
|
key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for CfgAtom {
|
impl fmt::Display for CfgAtom {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -66,9 +66,9 @@ impl DnfExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.enabled.sort_unstable_by(compare);
|
res.enabled.sort_unstable();
|
||||||
res.enabled.dedup();
|
res.enabled.dedup();
|
||||||
res.disabled.sort_unstable_by(compare);
|
res.disabled.sort_unstable();
|
||||||
res.disabled.dedup();
|
res.disabled.dedup();
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
@ -114,25 +114,14 @@ impl DnfExpr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Undo the FxHashMap randomization for consistent output.
|
// Undo the FxHashMap randomization for consistent output.
|
||||||
diff.enable.sort_unstable_by(compare);
|
diff.enable.sort_unstable();
|
||||||
diff.disable.sort_unstable_by(compare);
|
diff.disable.sort_unstable();
|
||||||
|
|
||||||
Some(diff)
|
Some(diff)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare(a: &CfgAtom, b: &CfgAtom) -> std::cmp::Ordering {
|
|
||||||
match (a, b) {
|
|
||||||
(CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()),
|
|
||||||
(CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less,
|
|
||||||
(CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater,
|
|
||||||
(CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => {
|
|
||||||
key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for DnfExpr {
|
impl fmt::Display for DnfExpr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if self.conjunctions.len() != 1 {
|
if self.conjunctions.len() != 1 {
|
||||||
|
@ -148,16 +148,20 @@ pub struct CfgDiff {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CfgDiff {
|
impl CfgDiff {
|
||||||
/// Create a new CfgDiff. Will return None if the same item appears more than once in the set
|
/// Create a new CfgDiff.
|
||||||
/// of both.
|
pub fn new(mut enable: Vec<CfgAtom>, mut disable: Vec<CfgAtom>) -> CfgDiff {
|
||||||
pub fn new(enable: Vec<CfgAtom>, disable: Vec<CfgAtom>) -> Option<CfgDiff> {
|
enable.sort();
|
||||||
let mut occupied = FxHashSet::default();
|
enable.dedup();
|
||||||
if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) {
|
disable.sort();
|
||||||
// was present
|
disable.dedup();
|
||||||
return None;
|
for i in (0..enable.len()).rev() {
|
||||||
|
if let Some(j) = disable.iter().position(|atom| *atom == enable[i]) {
|
||||||
|
enable.remove(i);
|
||||||
|
disable.remove(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CfgDiff { enable, disable })
|
CfgDiff { enable, disable }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the total number of atoms changed by this diff.
|
/// Returns the total number of atoms changed by this diff.
|
||||||
|
@ -166,7 +166,7 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
|
|||||||
#[test]
|
#[test]
|
||||||
fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||||
let cfg_overrides = CfgOverrides {
|
let cfg_overrides = CfgOverrides {
|
||||||
global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(),
|
global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]),
|
||||||
selective: Default::default(),
|
selective: Default::default(),
|
||||||
};
|
};
|
||||||
let (crate_graph, _proc_macros) =
|
let (crate_graph, _proc_macros) =
|
||||||
@ -185,7 +185,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
|||||||
global: Default::default(),
|
global: Default::default(),
|
||||||
selective: std::iter::once((
|
selective: std::iter::once((
|
||||||
"libc".to_owned(),
|
"libc".to_owned(),
|
||||||
CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(),
|
CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]),
|
||||||
))
|
))
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
@ -1522,7 +1522,7 @@ fn extend_crate_graph_with_sysroot(
|
|||||||
) -> (SysrootPublicDeps, Option<CrateId>) {
|
) -> (SysrootPublicDeps, Option<CrateId>) {
|
||||||
let mut pub_deps = vec![];
|
let mut pub_deps = vec![];
|
||||||
let mut libproc_macro = None;
|
let mut libproc_macro = None;
|
||||||
let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
|
let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]);
|
||||||
for (cid, c) in sysroot_crate_graph.iter_mut() {
|
for (cid, c) in sysroot_crate_graph.iter_mut() {
|
||||||
// uninject `test` flag so `core` keeps working.
|
// uninject `test` flag so `core` keeps working.
|
||||||
Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
|
Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
|
||||||
@ -1596,8 +1596,7 @@ fn sysroot_to_crate_graph(
|
|||||||
CfgAtom::Flag(sym::miri.clone()),
|
CfgAtom::Flag(sym::miri.clone()),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
)
|
),
|
||||||
.unwrap(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
&WorkspaceBuildScripts::default(),
|
&WorkspaceBuildScripts::default(),
|
||||||
@ -1620,8 +1619,7 @@ fn sysroot_to_crate_graph(
|
|||||||
CfgAtom::Flag(sym::miri.clone()),
|
CfgAtom::Flag(sym::miri.clone()),
|
||||||
],
|
],
|
||||||
vec![],
|
vec![],
|
||||||
)
|
),
|
||||||
.unwrap(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
@ -69,7 +69,7 @@ impl flags::AnalysisStats {
|
|||||||
all_targets: true,
|
all_targets: true,
|
||||||
set_test: !self.no_test,
|
set_test: !self.no_test,
|
||||||
cfg_overrides: CfgOverrides {
|
cfg_overrides: CfgOverrides {
|
||||||
global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]).unwrap(),
|
global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]),
|
||||||
selective: Default::default(),
|
selective: Default::default(),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -18,7 +18,7 @@ use ide_db::{
|
|||||||
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
||||||
SnippetCap,
|
SnippetCap,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::{Either, Itertools};
|
||||||
use paths::{Utf8Path, Utf8PathBuf};
|
use paths::{Utf8Path, Utf8PathBuf};
|
||||||
use project_model::{
|
use project_model::{
|
||||||
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand,
|
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand,
|
||||||
@ -589,6 +589,10 @@ config_data! {
|
|||||||
/// avoid checking unnecessary things.
|
/// avoid checking unnecessary things.
|
||||||
cargo_buildScripts_useRustcWrapper: bool = true,
|
cargo_buildScripts_useRustcWrapper: bool = true,
|
||||||
/// List of cfg options to enable with the given values.
|
/// List of cfg options to enable with the given values.
|
||||||
|
///
|
||||||
|
/// To enable a name without a value, use `"key"`.
|
||||||
|
/// To enable a name with a value, use `"key=value"`.
|
||||||
|
/// To disable, prefix the entry with a `!`.
|
||||||
cargo_cfgs: Vec<String> = {
|
cargo_cfgs: Vec<String> = {
|
||||||
vec!["debug_assertions".into(), "miri".into()]
|
vec!["debug_assertions".into(), "miri".into()]
|
||||||
},
|
},
|
||||||
@ -1980,27 +1984,35 @@ impl Config {
|
|||||||
rustc_source,
|
rustc_source,
|
||||||
extra_includes,
|
extra_includes,
|
||||||
cfg_overrides: project_model::CfgOverrides {
|
cfg_overrides: project_model::CfgOverrides {
|
||||||
global: CfgDiff::new(
|
global: {
|
||||||
self.cargo_cfgs(source_root)
|
let (enabled, disabled): (Vec<_>, Vec<_>) =
|
||||||
.iter()
|
self.cargo_cfgs(source_root).iter().partition_map(|s| {
|
||||||
// parse any cfg setting formatted as key=value or just key (without value)
|
s.strip_prefix("!").map_or(Either::Left(s), Either::Right)
|
||||||
.filter_map(|s| {
|
});
|
||||||
let mut sp = s.splitn(2, "=");
|
CfgDiff::new(
|
||||||
let key = sp.next();
|
enabled
|
||||||
let val = sp.next();
|
.into_iter()
|
||||||
key.map(|key| (key, val))
|
// parse any cfg setting formatted as key=value or just key (without value)
|
||||||
})
|
.map(|s| match s.split_once("=") {
|
||||||
.map(|(key, val)| match val {
|
Some((key, val)) => CfgAtom::KeyValue {
|
||||||
Some(val) => CfgAtom::KeyValue {
|
key: Symbol::intern(key),
|
||||||
key: Symbol::intern(key),
|
value: Symbol::intern(val),
|
||||||
value: Symbol::intern(val),
|
},
|
||||||
},
|
None => CfgAtom::Flag(Symbol::intern(s)),
|
||||||
None => CfgAtom::Flag(Symbol::intern(key)),
|
})
|
||||||
})
|
.collect(),
|
||||||
.collect(),
|
disabled
|
||||||
vec![],
|
.into_iter()
|
||||||
)
|
.map(|s| match s.split_once("=") {
|
||||||
.unwrap(),
|
Some((key, val)) => CfgAtom::KeyValue {
|
||||||
|
key: Symbol::intern(key),
|
||||||
|
value: Symbol::intern(val),
|
||||||
|
},
|
||||||
|
None => CfgAtom::Flag(Symbol::intern(s)),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
},
|
||||||
selective: Default::default(),
|
selective: Default::default(),
|
||||||
},
|
},
|
||||||
wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(source_root),
|
wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(source_root),
|
||||||
|
@ -244,8 +244,14 @@ struct FlycheckActor {
|
|||||||
/// The receiver side of the channel mentioned above.
|
/// The receiver side of the channel mentioned above.
|
||||||
command_receiver: Option<Receiver<CargoCheckMessage>>,
|
command_receiver: Option<Receiver<CargoCheckMessage>>,
|
||||||
diagnostics_cleared_for: FxHashSet<Arc<PackageId>>,
|
diagnostics_cleared_for: FxHashSet<Arc<PackageId>>,
|
||||||
diagnostics_cleared_for_all: bool,
|
diagnostics_received: DiagnosticsReceived,
|
||||||
diagnostics_received: bool,
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum DiagnosticsReceived {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
YesAndClearedForAll,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
@ -276,8 +282,7 @@ impl FlycheckActor {
|
|||||||
command_handle: None,
|
command_handle: None,
|
||||||
command_receiver: None,
|
command_receiver: None,
|
||||||
diagnostics_cleared_for: Default::default(),
|
diagnostics_cleared_for: Default::default(),
|
||||||
diagnostics_cleared_for_all: false,
|
diagnostics_received: DiagnosticsReceived::No,
|
||||||
diagnostics_received: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +359,7 @@ impl FlycheckActor {
|
|||||||
error
|
error
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !self.diagnostics_received {
|
if self.diagnostics_received == DiagnosticsReceived::No {
|
||||||
tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
|
tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
|
||||||
// We finished without receiving any diagnostics.
|
// We finished without receiving any diagnostics.
|
||||||
// Clear everything for good measure
|
// Clear everything for good measure
|
||||||
@ -396,7 +401,7 @@ impl FlycheckActor {
|
|||||||
package_id = package_id.as_ref().map(|it| &it.repr),
|
package_id = package_id.as_ref().map(|it| &it.repr),
|
||||||
"diagnostic received"
|
"diagnostic received"
|
||||||
);
|
);
|
||||||
self.diagnostics_received = true;
|
self.diagnostics_received = DiagnosticsReceived::Yes;
|
||||||
if let Some(package_id) = &package_id {
|
if let Some(package_id) = &package_id {
|
||||||
if self.diagnostics_cleared_for.insert(package_id.clone()) {
|
if self.diagnostics_cleared_for.insert(package_id.clone()) {
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
@ -409,8 +414,10 @@ impl FlycheckActor {
|
|||||||
package_id: Some(package_id.clone()),
|
package_id: Some(package_id.clone()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if !self.diagnostics_cleared_for_all {
|
} else if self.diagnostics_received
|
||||||
self.diagnostics_cleared_for_all = true;
|
!= DiagnosticsReceived::YesAndClearedForAll
|
||||||
|
{
|
||||||
|
self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll;
|
||||||
self.send(FlycheckMessage::ClearDiagnostics {
|
self.send(FlycheckMessage::ClearDiagnostics {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
package_id: None,
|
package_id: None,
|
||||||
@ -445,8 +452,7 @@ impl FlycheckActor {
|
|||||||
|
|
||||||
fn clear_diagnostics_state(&mut self) {
|
fn clear_diagnostics_state(&mut self) {
|
||||||
self.diagnostics_cleared_for.clear();
|
self.diagnostics_cleared_for.clear();
|
||||||
self.diagnostics_cleared_for_all = false;
|
self.diagnostics_received = DiagnosticsReceived::No;
|
||||||
self.diagnostics_received = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a `Command` object for checking the user's code. If the user
|
/// Construct a `Command` object for checking the user's code. If the user
|
||||||
|
@ -102,6 +102,10 @@ Default:
|
|||||||
|
|
||||||
List of cfg options to enable with the given values.
|
List of cfg options to enable with the given values.
|
||||||
|
|
||||||
|
To enable a name without a value, use `"key"`.
|
||||||
|
To enable a name with a value, use `"key=value"`.
|
||||||
|
To disable, prefix the entry with a `!`.
|
||||||
|
|
||||||
|
|
||||||
**rust-analyzer.cargo.extraArgs** (default: [])
|
**rust-analyzer.cargo.extraArgs** (default: [])
|
||||||
|
|
||||||
|
@ -818,7 +818,7 @@
|
|||||||
"title": "cargo",
|
"title": "cargo",
|
||||||
"properties": {
|
"properties": {
|
||||||
"rust-analyzer.cargo.cfgs": {
|
"rust-analyzer.cargo.cfgs": {
|
||||||
"markdownDescription": "List of cfg options to enable with the given values.",
|
"markdownDescription": "List of cfg options to enable with the given values.\n\nTo enable a name without a value, use `\"key\"`.\nTo enable a name with a value, use `\"key=value\"`.\nTo disable, prefix the entry with a `!`.",
|
||||||
"default": [
|
"default": [
|
||||||
"debug_assertions",
|
"debug_assertions",
|
||||||
"miri"
|
"miri"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user