aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_editor/src/folding_ranges.rs74
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs7
-rw-r--r--crates/test_utils/src/lib.rs39
3 files changed, 78 insertions, 42 deletions
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs
index 2a8fa3cda..da542ecf0 100644
--- a/crates/ra_editor/src/folding_ranges.rs
+++ b/crates/ra_editor/src/folding_ranges.rs
@@ -10,6 +10,7 @@ use ra_syntax::{
10pub enum FoldKind { 10pub enum FoldKind {
11 Comment, 11 Comment,
12 Imports, 12 Imports,
13 Block,
13} 14}
14 15
15#[derive(Debug)] 16#[derive(Debug)]
@@ -62,6 +63,8 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
62 match kind { 63 match kind {
63 COMMENT => Some(FoldKind::Comment), 64 COMMENT => Some(FoldKind::Comment),
64 USE_ITEM => Some(FoldKind::Imports), 65 USE_ITEM => Some(FoldKind::Imports),
66 NAMED_FIELD_DEF_LIST | FIELD_PAT_LIST | ITEM_LIST | EXTERN_ITEM_LIST | USE_TREE_LIST
67 | BLOCK | ENUM_VARIANT_LIST => Some(FoldKind::Block),
65 _ => None, 68 _ => None,
66 } 69 }
67} 70}
@@ -170,7 +173,7 @@ mod tests {
170 use test_utils::extract_ranges; 173 use test_utils::extract_ranges;
171 174
172 fn do_check(text: &str, fold_kinds: &[FoldKind]) { 175 fn do_check(text: &str, fold_kinds: &[FoldKind]) {
173 let (ranges, text) = extract_ranges(text); 176 let (ranges, text) = extract_ranges(text, "fold");
174 let file = SourceFileNode::parse(&text); 177 let file = SourceFileNode::parse(&text);
175 let folds = folding_ranges(&file); 178 let folds = folding_ranges(&file);
176 179
@@ -198,26 +201,27 @@ mod tests {
198 #[test] 201 #[test]
199 fn test_fold_comments() { 202 fn test_fold_comments() {
200 let text = r#" 203 let text = r#"
201<|>// Hello 204<fold>// Hello
202// this is a multiline 205// this is a multiline
203// comment 206// comment
204//<|> 207//</fold>
205 208
206// But this is not 209// But this is not
207 210
208fn main() { 211fn main() <fold>{
209 <|>// We should 212 <fold>// We should
210 // also 213 // also
211 // fold 214 // fold
212 // this one.<|> 215 // this one.</fold>
213 <|>//! But this one is different 216 <fold>//! But this one is different
214 //! because it has another flavor<|> 217 //! because it has another flavor</fold>
215 <|>/* As does this 218 <fold>/* As does this
216 multiline comment */<|> 219 multiline comment */</fold>
217}"#; 220}</fold>"#;
218 221
219 let fold_kinds = &[ 222 let fold_kinds = &[
220 FoldKind::Comment, 223 FoldKind::Comment,
224 FoldKind::Block,
221 FoldKind::Comment, 225 FoldKind::Comment,
222 FoldKind::Comment, 226 FoldKind::Comment,
223 FoldKind::Comment, 227 FoldKind::Comment,
@@ -228,60 +232,66 @@ fn main() {
228 #[test] 232 #[test]
229 fn test_fold_imports() { 233 fn test_fold_imports() {
230 let text = r#" 234 let text = r#"
231<|>use std::{ 235<fold>use std::<fold>{
232 str, 236 str,
233 vec, 237 vec,
234 io as iop 238 io as iop
235};<|> 239}</fold>;</fold>
236 240
237fn main() { 241fn main() <fold>{
238}"#; 242}</fold>"#;
239 243
240 let folds = &[FoldKind::Imports]; 244 let folds = &[FoldKind::Imports, FoldKind::Block, FoldKind::Block];
241 do_check(text, folds); 245 do_check(text, folds);
242 } 246 }
243 247
244 #[test] 248 #[test]
245 fn test_fold_import_groups() { 249 fn test_fold_import_groups() {
246 let text = r#" 250 let text = r#"
247<|>use std::str; 251<fold>use std::str;
248use std::vec; 252use std::vec;
249use std::io as iop;<|> 253use std::io as iop;</fold>
250 254
251<|>use std::mem; 255<fold>use std::mem;
252use std::f64;<|> 256use std::f64;</fold>
253 257
254use std::collections::HashMap; 258use std::collections::HashMap;
255// Some random comment 259// Some random comment
256use std::collections::VecDeque; 260use std::collections::VecDeque;
257 261
258fn main() { 262fn main() <fold>{
259}"#; 263}</fold>"#;
260 264
261 let folds = &[FoldKind::Imports, FoldKind::Imports]; 265 let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Block];
262 do_check(text, folds); 266 do_check(text, folds);
263 } 267 }
264 268
265 #[test] 269 #[test]
266 fn test_fold_import_and_groups() { 270 fn test_fold_import_and_groups() {
267 let text = r#" 271 let text = r#"
268<|>use std::str; 272<fold>use std::str;
269use std::vec; 273use std::vec;
270use std::io as iop;<|> 274use std::io as iop;</fold>
271 275
272<|>use std::mem; 276<fold>use std::mem;
273use std::f64;<|> 277use std::f64;</fold>
274 278
275<|>use std::collections::{ 279<fold>use std::collections::<fold>{
276 HashMap, 280 HashMap,
277 VecDeque, 281 VecDeque,
278};<|> 282}</fold>;</fold>
279// Some random comment 283// Some random comment
280 284
281fn main() { 285fn main() <fold>{
282}"#; 286}</fold>"#;
283 287
284 let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Imports]; 288 let folds = &[
289 FoldKind::Imports,
290 FoldKind::Imports,
291 FoldKind::Imports,
292 FoldKind::Block,
293 FoldKind::Block,
294 ];
285 do_check(text, folds); 295 do_check(text, folds);
286 } 296 }
287 297
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 572ae7fb5..801966304 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -446,8 +446,9 @@ pub fn handle_folding_range(
446 .into_iter() 446 .into_iter()
447 .map(|fold| { 447 .map(|fold| {
448 let kind = match fold.kind { 448 let kind = match fold.kind {
449 FoldKind::Comment => FoldingRangeKind::Comment, 449 FoldKind::Comment => Some(FoldingRangeKind::Comment),
450 FoldKind::Imports => FoldingRangeKind::Imports, 450 FoldKind::Imports => Some(FoldingRangeKind::Imports),
451 FoldKind::Block => None,
451 }; 452 };
452 let range = fold.range.conv_with(&line_index); 453 let range = fold.range.conv_with(&line_index);
453 FoldingRange { 454 FoldingRange {
@@ -455,7 +456,7 @@ pub fn handle_folding_range(
455 start_character: Some(range.start.character), 456 start_character: Some(range.start.character),
456 end_line: range.end.line, 457 end_line: range.end.line,
457 end_character: Some(range.start.character), 458 end_character: Some(range.start.character),
458 kind: Some(kind), 459 kind,
459 } 460 }
460 }) 461 })
461 .collect(), 462 .collect(),
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 0a94adb74..1ae800d7c 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -66,15 +66,40 @@ pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> {
66 Some((TextRange::from_to(start, end), text)) 66 Some((TextRange::from_to(start, end), text))
67} 67}
68 68
69pub fn extract_ranges(text: &str) -> (Vec<TextRange>, String) { 69/// Extracts ranges, marked with `<tag> </tag>` paris from the `text`
70pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) {
71 let open = format!("<{}>", tag);
72 let close = format!("</{}>", tag);
70 let mut ranges = Vec::new(); 73 let mut ranges = Vec::new();
71 let mut text = String::from(text); 74 let mut res = String::new();
72 while let Some((range, new_text)) = try_extract_range(&text) { 75 let mut stack = Vec::new();
73 text = new_text; 76 loop {
74 ranges.push(range); 77 match text.find('<') {
78 None => {
79 res.push_str(text);
80 break;
81 }
82 Some(i) => {
83 res.push_str(&text[..i]);
84 text = &text[i..];
85 if text.starts_with(&open) {
86 text = &text[open.len()..];
87 let from = TextUnit::of_str(&res);
88 stack.push(from);
89 } else if text.starts_with(&close) {
90 text = &text[close.len()..];
91 let from = stack
92 .pop()
93 .unwrap_or_else(|| panic!("unmatched </{}>", tag));
94 let to = TextUnit::of_str(&res);
95 ranges.push(TextRange::from_to(from, to));
96 }
97 }
98 }
75 } 99 }
76 100 assert!(stack.is_empty(), "unmatched <{}>", tag);
77 (ranges, text) 101 ranges.sort_by_key(|r| (r.start(), r.end()));
102 (ranges, res)
78} 103}
79 104
80pub fn add_cursor(text: &str, offset: TextUnit) -> String { 105pub fn add_cursor(text: &str, offset: TextUnit) -> String {