aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils
diff options
context:
space:
mode:
Diffstat (limited to 'crates/test_utils')
-rw-r--r--crates/test_utils/src/lib.rs50
1 files changed, 44 insertions, 6 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index d55bae62a..d9c22c180 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -11,6 +11,7 @@ mod fixture;
11mod assert_linear; 11mod assert_linear;
12 12
13use std::{ 13use std::{
14 collections::BTreeMap,
14 convert::{TryFrom, TryInto}, 15 convert::{TryFrom, TryInto},
15 env, fs, 16 env, fs,
16 path::{Path, PathBuf}, 17 path::{Path, PathBuf},
@@ -205,14 +206,25 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
205/// 206///
206/// // ^^^ first line 207/// // ^^^ first line
207/// // | second line 208/// // | second line
209///
210/// Annotations point to the last line that actually was long enough for the
211/// range, not counting annotations themselves. So overlapping annotations are
212/// possible:
213/// ```no_run
214/// // stuff other stuff
215/// // ^^ 'st'
216/// // ^^^^^ 'stuff'
217/// // ^^^^^^^^^^^ 'other stuff'
218/// ```
208pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { 219pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
209 let mut res = Vec::new(); 220 let mut res = Vec::new();
210 let mut prev_line_start: Option<TextSize> = Some(0.into()); 221 // map from line length to beginning of last line that had that length
222 let mut line_start_map = BTreeMap::new();
211 let mut line_start: TextSize = 0.into(); 223 let mut line_start: TextSize = 0.into();
212 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); 224 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
213 for line in text.split_inclusive('\n') { 225 for line in text.split_inclusive('\n') {
214 let mut this_line_annotations = Vec::new(); 226 let mut this_line_annotations = Vec::new();
215 if let Some(idx) = line.find("//") { 227 let line_length = if let Some(idx) = line.find("//") {
216 let annotation_offset = TextSize::of(&line[..idx + "//".len()]); 228 let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
217 for annotation in extract_line_annotations(&line[idx + "//".len()..]) { 229 for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
218 match annotation { 230 match annotation {
@@ -222,7 +234,9 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
222 let range = if file { 234 let range = if file {
223 TextRange::up_to(TextSize::of(text)) 235 TextRange::up_to(TextSize::of(text))
224 } else { 236 } else {
225 range + prev_line_start.unwrap() 237 let line_start = line_start_map.range(range.end()..).next().unwrap();
238
239 range + line_start.1
226 }; 240 };
227 res.push((range, content)) 241 res.push((range, content))
228 } 242 }
@@ -238,9 +252,14 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
238 } 252 }
239 } 253 }
240 } 254 }
241 } 255 idx.try_into().unwrap()
256 } else {
257 TextSize::of(line)
258 };
259
260 line_start_map = line_start_map.split_off(&line_length);
261 line_start_map.insert(line_length, line_start);
242 262
243 prev_line_start = Some(line_start);
244 line_start += TextSize::of(line); 263 line_start += TextSize::of(line);
245 264
246 prev_line_annotations = this_line_annotations; 265 prev_line_annotations = this_line_annotations;
@@ -296,7 +315,7 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
296} 315}
297 316
298#[test] 317#[test]
299fn test_extract_annotations() { 318fn test_extract_annotations_1() {
300 let text = stdx::trim_indent( 319 let text = stdx::trim_indent(
301 r#" 320 r#"
302fn main() { 321fn main() {
@@ -321,6 +340,25 @@ fn main() {
321 assert_eq!(res[3].0.len(), 115); 340 assert_eq!(res[3].0.len(), 115);
322} 341}
323 342
343#[test]
344fn test_extract_annotations_2() {
345 let text = stdx::trim_indent(
346 r#"
347fn main() {
348 (x, y);
349 //^ a
350 // ^ b
351 //^^^^^^^^ c
352}"#,
353 );
354 let res = extract_annotations(&text)
355 .into_iter()
356 .map(|(range, ann)| (&text[range], ann))
357 .collect::<Vec<_>>();
358
359 assert_eq!(res, [("x", "a".into()), ("y", "b".into()), ("(x, y)", "c".into())]);
360}
361
324/// Returns `false` if slow tests should not run, otherwise returns `true` and 362/// Returns `false` if slow tests should not run, otherwise returns `true` and
325/// also creates a file at `./target/.slow_tests_cookie` which serves as a flag 363/// also creates a file at `./target/.slow_tests_cookie` which serves as a flag
326/// that slow tests did run. 364/// that slow tests did run.