aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/folding_ranges.rs
diff options
context:
space:
mode:
authorLuciano Bestia <[email protected]>2021-01-18 18:45:42 +0000
committerLuciano Bestia <[email protected]>2021-01-18 18:45:42 +0000
commit9f1d341ee9bf399fa8fa2a5d2fb5f91e1b319702 (patch)
tree2aef832786e9d6eaccfe7cf566113fd35421a46a /crates/ide/src/folding_ranges.rs
parenta1c72451bb8b657f4e5a015428112090402de106 (diff)
added region folding
Diffstat (limited to 'crates/ide/src/folding_ranges.rs')
-rw-r--r--crates/ide/src/folding_ranges.rs76
1 files changed, 68 insertions, 8 deletions
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs
index 45170dd29..99f0c3c99 100644
--- a/crates/ide/src/folding_ranges.rs
+++ b/crates/ide/src/folding_ranges.rs
@@ -6,9 +6,11 @@ use syntax::{
6 ast::{self, AstNode, AstToken, VisibilityOwner}, 6 ast::{self, AstNode, AstToken, VisibilityOwner},
7 Direction, NodeOrToken, SourceFile, 7 Direction, NodeOrToken, SourceFile,
8 SyntaxKind::{self, *}, 8 SyntaxKind::{self, *},
9 SyntaxNode, TextRange, 9 SyntaxNode, TextRange, TextSize,
10}; 10};
11 11
12use lazy_static::lazy_static;
13
12#[derive(Debug, PartialEq, Eq)] 14#[derive(Debug, PartialEq, Eq)]
13pub enum FoldKind { 15pub enum FoldKind {
14 Comment, 16 Comment,
@@ -16,6 +18,7 @@ pub enum FoldKind {
16 Mods, 18 Mods,
17 Block, 19 Block,
18 ArgList, 20 ArgList,
21 Region,
19} 22}
20 23
21#[derive(Debug)] 24#[derive(Debug)]
@@ -29,6 +32,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
29 let mut visited_comments = FxHashSet::default(); 32 let mut visited_comments = FxHashSet::default();
30 let mut visited_imports = FxHashSet::default(); 33 let mut visited_imports = FxHashSet::default();
31 let mut visited_mods = FxHashSet::default(); 34 let mut visited_mods = FxHashSet::default();
35 // regions can be nested, here is a LIFO buffer
36 let mut regions_starts: Vec<TextSize> = vec![];
32 37
33 for element in file.syntax().descendants_with_tokens() { 38 for element in file.syntax().descendants_with_tokens() {
34 // Fold items that span multiple lines 39 // Fold items that span multiple lines
@@ -48,10 +53,32 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
48 // Fold groups of comments 53 // Fold groups of comments
49 if let Some(comment) = ast::Comment::cast(token) { 54 if let Some(comment) = ast::Comment::cast(token) {
50 if !visited_comments.contains(&comment) { 55 if !visited_comments.contains(&comment) {
51 if let Some(range) = 56 // regions are not really comments
52 contiguous_range_for_comment(comment, &mut visited_comments) 57 use regex::Regex;
53 { 58 lazy_static! {
54 res.push(Fold { range, kind: FoldKind::Comment }) 59 static ref RE_START: Regex =
60 Regex::new(r"^\s*//\s*#?region\b").unwrap();
61 static ref RE_END: Regex =
62 Regex::new(r"^\s*//\s*#?endregion\b").unwrap();
63 }
64 if RE_START.is_match(comment.text()) {
65 regions_starts.push(comment.syntax().text_range().start());
66 } else if RE_END.is_match(comment.text()) {
67 if !regions_starts.is_empty() {
68 res.push(Fold {
69 range: TextRange::new(
70 regions_starts.pop().unwrap(),
71 comment.syntax().text_range().end(),
72 ),
73 kind: FoldKind::Region,
74 })
75 }
76 } else {
77 if let Some(range) =
78 contiguous_range_for_comment(comment, &mut visited_comments)
79 {
80 res.push(Fold { range, kind: FoldKind::Comment })
81 }
55 } 82 }
56 } 83 }
57 } 84 }
@@ -175,9 +202,21 @@ fn contiguous_range_for_comment(
175 } 202 }
176 if let Some(c) = ast::Comment::cast(token) { 203 if let Some(c) = ast::Comment::cast(token) {
177 if c.kind() == group_kind { 204 if c.kind() == group_kind {
178 visited.insert(c.clone()); 205 // regions are not really comments
179 last = c; 206 use regex::Regex;
180 continue; 207 lazy_static! {
208 static ref RE_START: Regex =
209 Regex::new(r"^\s*//\s*#?region\b").unwrap();
210 static ref RE_END: Regex =
211 Regex::new(r"^\s*//\s*#?endregion\b").unwrap();
212 }
213 if RE_START.is_match(c.text()) || RE_END.is_match(c.text()) {
214 break;
215 } else {
216 visited.insert(c.clone());
217 last = c;
218 continue;
219 }
181 } 220 }
182 } 221 }
183 // The comment group ends because either: 222 // The comment group ends because either:
@@ -224,6 +263,7 @@ mod tests {
224 FoldKind::Mods => "mods", 263 FoldKind::Mods => "mods",
225 FoldKind::Block => "block", 264 FoldKind::Block => "block",
226 FoldKind::ArgList => "arglist", 265 FoldKind::ArgList => "arglist",
266 FoldKind::Region => "region",
227 }; 267 };
228 assert_eq!(kind, &attr.unwrap()); 268 assert_eq!(kind, &attr.unwrap());
229 } 269 }
@@ -418,4 +458,24 @@ fn foo<fold arglist>(
418"#, 458"#,
419 ) 459 )
420 } 460 }
461
462 #[test]
463 fn fold_region() {
464 log_init_for_test_debug();
465 // only error level log is printed on the terminal
466 log::error!("test fold_region");
467 check(
468 r#"
469// 1. some normal comment
470<fold region>// region: test
471// 2. some normal comment
472calling_function(x,y);
473// endregion: test</fold>
474"#,
475 )
476 }
477
478 fn log_init_for_test_debug() {
479 let _ = env_logger::builder().is_test(true).try_init();
480 }
421} 481}