mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 22:31:43 +00:00
Fix DNF construction, add proptest
This commit is contained in:
parent
20f3792d10
commit
e6255356d2
5 changed files with 99 additions and 4 deletions
|
@ -50,6 +50,7 @@ impl fmt::Display for CfgAtom {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
|
||||
pub enum CfgExpr {
|
||||
Invalid,
|
||||
Atom(CfgAtom),
|
||||
|
@ -128,3 +129,17 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
|
|||
}
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl arbitrary::Arbitrary<'_> for CfgAtom {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
|
||||
match u.int_in_range(0..=1)? {
|
||||
0 => Ok(CfgAtom::Flag(String::arbitrary(u)?.into())),
|
||||
1 => Ok(CfgAtom::KeyValue {
|
||||
key: String::arbitrary(u)?.into(),
|
||||
value: String::arbitrary(u)?.into(),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,11 +255,11 @@ impl Builder {
|
|||
fn make_dnf(expr: CfgExpr) -> CfgExpr {
|
||||
match expr {
|
||||
CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => expr,
|
||||
CfgExpr::Any(e) => CfgExpr::Any(e.into_iter().map(make_dnf).collect()),
|
||||
CfgExpr::Any(e) => flatten(CfgExpr::Any(e.into_iter().map(make_dnf).collect())),
|
||||
CfgExpr::All(e) => {
|
||||
let e = e.into_iter().map(make_nnf).collect::<Vec<_>>();
|
||||
let e = e.into_iter().map(make_dnf).collect::<Vec<_>>();
|
||||
|
||||
CfgExpr::Any(distribute_conj(&e))
|
||||
flatten(CfgExpr::Any(distribute_conj(&e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut out = Vec::new();
|
||||
let mut out = Vec::new(); // contains only `all()`
|
||||
let mut with = Vec::new();
|
||||
|
||||
go(&mut out, &mut with, conj);
|
||||
|
@ -318,3 +318,28 @@ fn make_nnf(expr: CfgExpr) -> CfgExpr {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Collapses nested `any()` and `all()` predicates.
|
||||
fn flatten(expr: CfgExpr) -> CfgExpr {
|
||||
match expr {
|
||||
CfgExpr::All(inner) => CfgExpr::All(
|
||||
inner
|
||||
.into_iter()
|
||||
.flat_map(|e| match e {
|
||||
CfgExpr::All(inner) => inner,
|
||||
_ => vec![e],
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
CfgExpr::Any(inner) => CfgExpr::Any(
|
||||
inner
|
||||
.into_iter()
|
||||
.flat_map(|e| match e {
|
||||
CfgExpr::Any(inner) => inner,
|
||||
_ => vec![e],
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
_ => expr,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use expect_test::{expect, Expect};
|
||||
use mbe::syntax_node_to_token_tree;
|
||||
use syntax::{ast, AstNode};
|
||||
|
@ -130,6 +131,18 @@ fn nested() {
|
|||
check_dnf("#![cfg(not(all(all(a, b))))]", expect![[r#"#![cfg(any(not(a), not(b)))]"#]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression() {
|
||||
check_dnf("#![cfg(all(not(not(any(any(any()))))))]", expect![[r##"#![cfg(any())]"##]]);
|
||||
check_dnf("#![cfg(all(any(all(any()))))]", expect![[r##"#![cfg(any())]"##]]);
|
||||
check_dnf("#![cfg(all(all(any())))]", expect![[r##"#![cfg(any())]"##]]);
|
||||
|
||||
check_dnf("#![cfg(all(all(any(), x)))]", expect![[r##"#![cfg(any())]"##]]);
|
||||
check_dnf("#![cfg(all(all(any()), x))]", expect![[r##"#![cfg(any())]"##]]);
|
||||
check_dnf("#![cfg(all(all(any(x))))]", expect![[r##"#![cfg(x)]"##]]);
|
||||
check_dnf("#![cfg(all(all(any(x), x)))]", expect![[r##"#![cfg(all(x, x))]"##]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hints() {
|
||||
let mut opts = CfgOptions::default();
|
||||
|
@ -191,3 +204,21 @@ fn why_inactive() {
|
|||
expect![["test and test2 are enabled and a is disabled"]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proptest() {
|
||||
const REPEATS: usize = 512;
|
||||
|
||||
let mut rng = oorandom::Rand32::new(123456789);
|
||||
let mut buf = Vec::new();
|
||||
for _ in 0..REPEATS {
|
||||
buf.clear();
|
||||
while buf.len() < 512 {
|
||||
buf.extend(rng.rand_u32().to_ne_bytes());
|
||||
}
|
||||
|
||||
let mut u = Unstructured::new(&buf);
|
||||
let cfg = CfgExpr::arbitrary(&mut u).unwrap();
|
||||
DnfExpr::new(cfg);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue