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 {