mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 11:17:13 +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 },
|
||||
}
|
||||
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -66,9 +66,9 @@ impl DnfExpr {
|
||||
}
|
||||
}
|
||||
|
||||
res.enabled.sort_unstable_by(compare);
|
||||
res.enabled.sort_unstable();
|
||||
res.enabled.dedup();
|
||||
res.disabled.sort_unstable_by(compare);
|
||||
res.disabled.sort_unstable();
|
||||
res.disabled.dedup();
|
||||
Some(res)
|
||||
}
|
||||
@ -114,25 +114,14 @@ impl DnfExpr {
|
||||
};
|
||||
|
||||
// Undo the FxHashMap randomization for consistent output.
|
||||
diff.enable.sort_unstable_by(compare);
|
||||
diff.disable.sort_unstable_by(compare);
|
||||
diff.enable.sort_unstable();
|
||||
diff.disable.sort_unstable();
|
||||
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.conjunctions.len() != 1 {
|
||||
|
@ -148,16 +148,20 @@ pub struct CfgDiff {
|
||||
}
|
||||
|
||||
impl CfgDiff {
|
||||
/// Create a new CfgDiff. Will return None if the same item appears more than once in the set
|
||||
/// of both.
|
||||
pub fn new(enable: Vec<CfgAtom>, disable: Vec<CfgAtom>) -> Option<CfgDiff> {
|
||||
let mut occupied = FxHashSet::default();
|
||||
if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) {
|
||||
// was present
|
||||
return None;
|
||||
/// Create a new CfgDiff.
|
||||
pub fn new(mut enable: Vec<CfgAtom>, mut disable: Vec<CfgAtom>) -> CfgDiff {
|
||||
enable.sort();
|
||||
enable.dedup();
|
||||
disable.sort();
|
||||
disable.dedup();
|
||||
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.
|
||||
|
@ -166,7 +166,7 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
|
||||
#[test]
|
||||
fn cargo_hello_world_project_model_with_wildcard_overrides() {
|
||||
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(),
|
||||
};
|
||||
let (crate_graph, _proc_macros) =
|
||||
@ -185,7 +185,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
|
||||
global: Default::default(),
|
||||
selective: std::iter::once((
|
||||
"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(),
|
||||
};
|
||||
|
@ -1522,7 +1522,7 @@ fn extend_crate_graph_with_sysroot(
|
||||
) -> (SysrootPublicDeps, Option<CrateId>) {
|
||||
let mut pub_deps = vec![];
|
||||
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() {
|
||||
// uninject `test` flag so `core` keeps working.
|
||||
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()),
|
||||
],
|
||||
vec![],
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
&WorkspaceBuildScripts::default(),
|
||||
@ -1620,8 +1619,7 @@ fn sysroot_to_crate_graph(
|
||||
CfgAtom::Flag(sym::miri.clone()),
|
||||
],
|
||||
vec![],
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
false,
|
||||
|
@ -69,7 +69,7 @@ impl flags::AnalysisStats {
|
||||
all_targets: true,
|
||||
set_test: !self.no_test,
|
||||
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(),
|
||||
},
|
||||
..Default::default()
|
||||
|
@ -18,7 +18,7 @@ use ide_db::{
|
||||
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
||||
SnippetCap,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use itertools::{Either, Itertools};
|
||||
use paths::{Utf8Path, Utf8PathBuf};
|
||||
use project_model::{
|
||||
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand,
|
||||
@ -589,6 +589,10 @@ config_data! {
|
||||
/// avoid checking unnecessary things.
|
||||
cargo_buildScripts_useRustcWrapper: bool = true,
|
||||
/// 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> = {
|
||||
vec!["debug_assertions".into(), "miri".into()]
|
||||
},
|
||||
@ -1980,27 +1984,35 @@ impl Config {
|
||||
rustc_source,
|
||||
extra_includes,
|
||||
cfg_overrides: project_model::CfgOverrides {
|
||||
global: CfgDiff::new(
|
||||
self.cargo_cfgs(source_root)
|
||||
.iter()
|
||||
global: {
|
||||
let (enabled, disabled): (Vec<_>, Vec<_>) =
|
||||
self.cargo_cfgs(source_root).iter().partition_map(|s| {
|
||||
s.strip_prefix("!").map_or(Either::Left(s), Either::Right)
|
||||
});
|
||||
CfgDiff::new(
|
||||
enabled
|
||||
.into_iter()
|
||||
// parse any cfg setting formatted as key=value or just key (without value)
|
||||
.filter_map(|s| {
|
||||
let mut sp = s.splitn(2, "=");
|
||||
let key = sp.next();
|
||||
let val = sp.next();
|
||||
key.map(|key| (key, val))
|
||||
})
|
||||
.map(|(key, val)| match val {
|
||||
Some(val) => CfgAtom::KeyValue {
|
||||
.map(|s| match s.split_once("=") {
|
||||
Some((key, val)) => CfgAtom::KeyValue {
|
||||
key: Symbol::intern(key),
|
||||
value: Symbol::intern(val),
|
||||
},
|
||||
None => CfgAtom::Flag(Symbol::intern(key)),
|
||||
None => CfgAtom::Flag(Symbol::intern(s)),
|
||||
})
|
||||
.collect(),
|
||||
disabled
|
||||
.into_iter()
|
||||
.map(|s| match s.split_once("=") {
|
||||
Some((key, val)) => CfgAtom::KeyValue {
|
||||
key: Symbol::intern(key),
|
||||
value: Symbol::intern(val),
|
||||
},
|
||||
None => CfgAtom::Flag(Symbol::intern(s)),
|
||||
})
|
||||
.collect(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap(),
|
||||
},
|
||||
selective: Default::default(),
|
||||
},
|
||||
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.
|
||||
command_receiver: Option<Receiver<CargoCheckMessage>>,
|
||||
diagnostics_cleared_for: FxHashSet<Arc<PackageId>>,
|
||||
diagnostics_cleared_for_all: bool,
|
||||
diagnostics_received: bool,
|
||||
diagnostics_received: DiagnosticsReceived,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum DiagnosticsReceived {
|
||||
Yes,
|
||||
No,
|
||||
YesAndClearedForAll,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@ -276,8 +282,7 @@ impl FlycheckActor {
|
||||
command_handle: None,
|
||||
command_receiver: None,
|
||||
diagnostics_cleared_for: Default::default(),
|
||||
diagnostics_cleared_for_all: false,
|
||||
diagnostics_received: false,
|
||||
diagnostics_received: DiagnosticsReceived::No,
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +359,7 @@ impl FlycheckActor {
|
||||
error
|
||||
);
|
||||
}
|
||||
if !self.diagnostics_received {
|
||||
if self.diagnostics_received == DiagnosticsReceived::No {
|
||||
tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
|
||||
// We finished without receiving any diagnostics.
|
||||
// Clear everything for good measure
|
||||
@ -396,7 +401,7 @@ impl FlycheckActor {
|
||||
package_id = package_id.as_ref().map(|it| &it.repr),
|
||||
"diagnostic received"
|
||||
);
|
||||
self.diagnostics_received = true;
|
||||
self.diagnostics_received = DiagnosticsReceived::Yes;
|
||||
if let Some(package_id) = &package_id {
|
||||
if self.diagnostics_cleared_for.insert(package_id.clone()) {
|
||||
tracing::trace!(
|
||||
@ -409,8 +414,10 @@ impl FlycheckActor {
|
||||
package_id: Some(package_id.clone()),
|
||||
});
|
||||
}
|
||||
} else if !self.diagnostics_cleared_for_all {
|
||||
self.diagnostics_cleared_for_all = true;
|
||||
} else if self.diagnostics_received
|
||||
!= DiagnosticsReceived::YesAndClearedForAll
|
||||
{
|
||||
self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll;
|
||||
self.send(FlycheckMessage::ClearDiagnostics {
|
||||
id: self.id,
|
||||
package_id: None,
|
||||
@ -445,8 +452,7 @@ impl FlycheckActor {
|
||||
|
||||
fn clear_diagnostics_state(&mut self) {
|
||||
self.diagnostics_cleared_for.clear();
|
||||
self.diagnostics_cleared_for_all = false;
|
||||
self.diagnostics_received = false;
|
||||
self.diagnostics_received = DiagnosticsReceived::No;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
|
||||
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: [])
|
||||
|
||||
|
@ -818,7 +818,7 @@
|
||||
"title": "cargo",
|
||||
"properties": {
|
||||
"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": [
|
||||
"debug_assertions",
|
||||
"miri"
|
||||
|
Loading…
x
Reference in New Issue
Block a user