aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_text_edit/src/test_utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_text_edit/src/test_utils.rs')
-rw-r--r--crates/ra_text_edit/src/test_utils.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/crates/ra_text_edit/src/test_utils.rs b/crates/ra_text_edit/src/test_utils.rs
new file mode 100644
index 000000000..745f21c93
--- /dev/null
+++ b/crates/ra_text_edit/src/test_utils.rs
@@ -0,0 +1,85 @@
1use proptest::prelude::*;
2use text_unit::{TextUnit, TextRange};
3use crate::{AtomTextEdit, TextEdit};
4
5pub fn arb_text() -> proptest::string::RegexGeneratorStrategy<String> {
6 // generate multiple newlines
7 proptest::string::string_regex("(.*\n?)*").unwrap()
8}
9
10fn text_offsets(text: &str) -> Vec<TextUnit> {
11 text.char_indices()
12 .map(|(i, _)| TextUnit::from_usize(i))
13 .collect()
14}
15
16pub fn arb_offset(text: &str) -> BoxedStrategy<TextUnit> {
17 let offsets = text_offsets(text);
18 // this is necessary to avoid "Uniform::new called with `low >= high`" panic
19 if offsets.is_empty() {
20 Just(TextUnit::from(0)).boxed()
21 } else {
22 prop::sample::select(offsets).boxed()
23 }
24}
25
26pub fn arb_text_edit(text: &str) -> BoxedStrategy<TextEdit> {
27 if text.is_empty() {
28 // only valid edits
29 return Just(vec![])
30 .boxed()
31 .prop_union(
32 arb_text()
33 .prop_map(|text| vec![AtomTextEdit::insert(TextUnit::from(0), text)])
34 .boxed(),
35 )
36 .prop_map(TextEdit::from_atoms)
37 .boxed();
38 }
39
40 let offsets = text_offsets(text);
41 let max_cuts = 7.min(offsets.len());
42
43 proptest::sample::subsequence(offsets, 0..max_cuts)
44 .prop_flat_map(|cuts| {
45 let strategies: Vec<_> = cuts
46 .chunks(2)
47 .map(|chunk| match chunk {
48 &[from, to] => {
49 let range = TextRange::from_to(from, to);
50 Just(AtomTextEdit::delete(range))
51 .boxed()
52 .prop_union(
53 arb_text()
54 .prop_map(move |text| AtomTextEdit::replace(range, text))
55 .boxed(),
56 )
57 .boxed()
58 }
59 &[x] => arb_text()
60 .prop_map(move |text| AtomTextEdit::insert(x, text))
61 .boxed(),
62 _ => unreachable!(),
63 })
64 .collect();
65 strategies
66 })
67 .prop_map(TextEdit::from_atoms)
68 .boxed()
69}
70
71#[derive(Debug, Clone)]
72pub struct ArbTextWithEdit {
73 pub text: String,
74 pub edit: TextEdit,
75}
76
77pub fn arb_text_with_edit() -> BoxedStrategy<ArbTextWithEdit> {
78 let text = arb_text();
79 text.prop_flat_map(|s| {
80 let edit = arb_text_edit(&s);
81 (Just(s), edit)
82 })
83 .prop_map(|(text, edit)| ArbTextWithEdit { text, edit })
84 .boxed()
85}