diff options
Diffstat (limited to 'crates/ide/src')
-rw-r--r-- | crates/ide/src/folding_ranges.rs | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs index 45170dd29..4b1b24562 100644 --- a/crates/ide/src/folding_ranges.rs +++ b/crates/ide/src/folding_ranges.rs | |||
@@ -6,7 +6,7 @@ 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 | ||
12 | #[derive(Debug, PartialEq, Eq)] | 12 | #[derive(Debug, PartialEq, Eq)] |
@@ -16,6 +16,7 @@ pub enum FoldKind { | |||
16 | Mods, | 16 | Mods, |
17 | Block, | 17 | Block, |
18 | ArgList, | 18 | ArgList, |
19 | Region, | ||
19 | } | 20 | } |
20 | 21 | ||
21 | #[derive(Debug)] | 22 | #[derive(Debug)] |
@@ -29,6 +30,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
29 | let mut visited_comments = FxHashSet::default(); | 30 | let mut visited_comments = FxHashSet::default(); |
30 | let mut visited_imports = FxHashSet::default(); | 31 | let mut visited_imports = FxHashSet::default(); |
31 | let mut visited_mods = FxHashSet::default(); | 32 | let mut visited_mods = FxHashSet::default(); |
33 | // regions can be nested, here is a LIFO buffer | ||
34 | let mut regions_starts: Vec<TextSize> = vec![]; | ||
32 | 35 | ||
33 | for element in file.syntax().descendants_with_tokens() { | 36 | for element in file.syntax().descendants_with_tokens() { |
34 | // Fold items that span multiple lines | 37 | // Fold items that span multiple lines |
@@ -48,10 +51,25 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> { | |||
48 | // Fold groups of comments | 51 | // Fold groups of comments |
49 | if let Some(comment) = ast::Comment::cast(token) { | 52 | if let Some(comment) = ast::Comment::cast(token) { |
50 | if !visited_comments.contains(&comment) { | 53 | if !visited_comments.contains(&comment) { |
51 | if let Some(range) = | 54 | // regions are not real comments |
52 | contiguous_range_for_comment(comment, &mut visited_comments) | 55 | if comment.text().trim().starts_with("// region:") { |
53 | { | 56 | regions_starts.push(comment.syntax().text_range().start()); |
54 | res.push(Fold { range, kind: FoldKind::Comment }) | 57 | } else if comment.text().trim().starts_with("// endregion") { |
58 | if let Some(region) = regions_starts.pop() { | ||
59 | res.push(Fold { | ||
60 | range: TextRange::new( | ||
61 | region, | ||
62 | comment.syntax().text_range().end(), | ||
63 | ), | ||
64 | kind: FoldKind::Region, | ||
65 | }) | ||
66 | } | ||
67 | } else { | ||
68 | if let Some(range) = | ||
69 | contiguous_range_for_comment(comment, &mut visited_comments) | ||
70 | { | ||
71 | res.push(Fold { range, kind: FoldKind::Comment }) | ||
72 | } | ||
55 | } | 73 | } |
56 | } | 74 | } |
57 | } | 75 | } |
@@ -175,9 +193,16 @@ fn contiguous_range_for_comment( | |||
175 | } | 193 | } |
176 | if let Some(c) = ast::Comment::cast(token) { | 194 | if let Some(c) = ast::Comment::cast(token) { |
177 | if c.kind() == group_kind { | 195 | if c.kind() == group_kind { |
178 | visited.insert(c.clone()); | 196 | // regions are not real comments |
179 | last = c; | 197 | if c.text().trim().starts_with("// region:") |
180 | continue; | 198 | || c.text().trim().starts_with("// endregion") |
199 | { | ||
200 | break; | ||
201 | } else { | ||
202 | visited.insert(c.clone()); | ||
203 | last = c; | ||
204 | continue; | ||
205 | } | ||
181 | } | 206 | } |
182 | } | 207 | } |
183 | // The comment group ends because either: | 208 | // The comment group ends because either: |
@@ -224,6 +249,7 @@ mod tests { | |||
224 | FoldKind::Mods => "mods", | 249 | FoldKind::Mods => "mods", |
225 | FoldKind::Block => "block", | 250 | FoldKind::Block => "block", |
226 | FoldKind::ArgList => "arglist", | 251 | FoldKind::ArgList => "arglist", |
252 | FoldKind::Region => "region", | ||
227 | }; | 253 | }; |
228 | assert_eq!(kind, &attr.unwrap()); | 254 | assert_eq!(kind, &attr.unwrap()); |
229 | } | 255 | } |
@@ -418,4 +444,17 @@ fn foo<fold arglist>( | |||
418 | "#, | 444 | "#, |
419 | ) | 445 | ) |
420 | } | 446 | } |
447 | |||
448 | #[test] | ||
449 | fn fold_region() { | ||
450 | check( | ||
451 | r#" | ||
452 | // 1. some normal comment | ||
453 | <fold region>// region: test | ||
454 | // 2. some normal comment | ||
455 | calling_function(x,y); | ||
456 | // endregion: test</fold> | ||
457 | "#, | ||
458 | ) | ||
459 | } | ||
421 | } | 460 | } |