diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs index 2a8fa3cda9..a4add8702c 100644 --- a/crates/ra_editor/src/folding_ranges.rs +++ b/crates/ra_editor/src/folding_ranges.rs @@ -170,7 +170,7 @@ mod tests { use test_utils::extract_ranges; fn do_check(text: &str, fold_kinds: &[FoldKind]) { - let (ranges, text) = extract_ranges(text); + let (ranges, text) = extract_ranges(text, "fold"); let file = SourceFileNode::parse(&text); let folds = folding_ranges(&file); @@ -198,22 +198,22 @@ mod tests { #[test] fn test_fold_comments() { let text = r#" -<|>// Hello +// Hello // this is a multiline // comment -//<|> +// // But this is not fn main() { - <|>// We should + // We should // also // fold - // this one.<|> - <|>//! But this one is different - //! because it has another flavor<|> - <|>/* As does this - multiline comment */<|> + // this one. + //! But this one is different + //! because it has another flavor + /* As does this + multiline comment */ }"#; let fold_kinds = &[ @@ -228,11 +228,11 @@ fn main() { #[test] fn test_fold_imports() { let text = r#" -<|>use std::{ +use std::{ str, vec, io as iop -};<|> +}; fn main() { }"#; @@ -244,12 +244,12 @@ fn main() { #[test] fn test_fold_import_groups() { let text = r#" -<|>use std::str; +use std::str; use std::vec; -use std::io as iop;<|> +use std::io as iop; -<|>use std::mem; -use std::f64;<|> +use std::mem; +use std::f64; use std::collections::HashMap; // Some random comment @@ -265,17 +265,17 @@ fn main() { #[test] fn test_fold_import_and_groups() { let text = r#" -<|>use std::str; +use std::str; use std::vec; -use std::io as iop;<|> +use std::io as iop; -<|>use std::mem; -use std::f64;<|> +use std::mem; +use std::f64; -<|>use std::collections::{ +use std::collections::{ HashMap, VecDeque, -};<|> +}; // Some random comment fn main() { diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 0a94adb740..894a22769b 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -66,15 +66,39 @@ pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> { Some((TextRange::from_to(start, end), text)) } -pub fn extract_ranges(text: &str) -> (Vec, String) { +/// Extracts ranges, marked with ` ` paris from the `text` +pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec, String) { + let open = format!("<{}>", tag); + let close = format!("", tag); let mut ranges = Vec::new(); - let mut text = String::from(text); - while let Some((range, new_text)) = try_extract_range(&text) { - text = new_text; - ranges.push(range); + let mut res = String::new(); + let mut stack = Vec::new(); + loop { + match text.find('<') { + None => { + res.push_str(text); + break; + } + Some(i) => { + res.push_str(&text[..i]); + text = &text[i..]; + if text.starts_with(&open) { + text = &text[open.len()..]; + let from = TextUnit::of_str(&res); + stack.push(from); + } else if text.starts_with(&close) { + text = &text[close.len()..]; + let from = stack + .pop() + .unwrap_or_else(|| panic!("unmatched ", tag)); + let to = TextUnit::of_str(&res); + ranges.push(TextRange::from_to(from, to)); + } + } + } } - - (ranges, text) + assert!(stack.is_empty(), "unmatched <{}>", tag); + (ranges, res) } pub fn add_cursor(text: &str, offset: TextUnit) -> String {