@@ -7,6 +7,9 @@ use syntax::{
7
7
SyntaxNode , TextRange , TextSize ,
8
8
} ;
9
9
10
+ const REGION_START : & str = "// region:" ;
11
+ const REGION_END : & str = "// endregion" ;
12
+
10
13
#[ derive( Debug , PartialEq , Eq ) ]
11
14
pub enum FoldKind {
12
15
Comment ,
@@ -30,17 +33,18 @@ pub struct Fold {
30
33
31
34
// Feature: Folding
32
35
//
33
- // Defines folding regions for curly braced blocks, runs of consecutive import
34
- // statements , and `region` / `endregion` comment markers.
36
+ // Defines folding regions for curly braced blocks, runs of consecutive use, mod, const or static
37
+ // items , and `region` / `endregion` comment markers.
35
38
pub ( crate ) fn folding_ranges ( file : & SourceFile ) -> Vec < Fold > {
36
39
let mut res = vec ! [ ] ;
37
40
let mut visited_comments = FxHashSet :: default ( ) ;
38
41
let mut visited_imports = FxHashSet :: default ( ) ;
39
42
let mut visited_mods = FxHashSet :: default ( ) ;
40
43
let mut visited_consts = FxHashSet :: default ( ) ;
41
44
let mut visited_statics = FxHashSet :: default ( ) ;
45
+
42
46
// regions can be nested, here is a LIFO buffer
43
- let mut regions_starts : Vec < TextSize > = vec ! [ ] ;
47
+ let mut region_starts : Vec < TextSize > = vec ! [ ] ;
44
48
45
49
for element in file. syntax ( ) . descendants_with_tokens ( ) {
46
50
// Fold items that span multiple lines
@@ -59,27 +63,23 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
59
63
NodeOrToken :: Token ( token) => {
60
64
// Fold groups of comments
61
65
if let Some ( comment) = ast:: Comment :: cast ( token) {
62
- if !visited_comments. contains ( & comment) {
63
- // regions are not real comments
64
- if comment. text ( ) . trim ( ) . starts_with ( "// region:" ) {
65
- regions_starts. push ( comment. syntax ( ) . text_range ( ) . start ( ) ) ;
66
- } else if comment. text ( ) . trim ( ) . starts_with ( "// endregion" ) {
67
- if let Some ( region) = regions_starts. pop ( ) {
68
- res. push ( Fold {
69
- range : TextRange :: new (
70
- region,
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
- }
66
+ if visited_comments. contains ( & comment) {
67
+ continue ;
68
+ }
69
+ let text = comment. text ( ) . trim_start ( ) ;
70
+ if text. starts_with ( REGION_START ) {
71
+ region_starts. push ( comment. syntax ( ) . text_range ( ) . start ( ) ) ;
72
+ } else if text. starts_with ( REGION_END ) {
73
+ if let Some ( region) = region_starts. pop ( ) {
74
+ res. push ( Fold {
75
+ range : TextRange :: new ( region, comment. syntax ( ) . text_range ( ) . end ( ) ) ,
76
+ kind : FoldKind :: Region ,
77
+ } )
82
78
}
79
+ } else if let Some ( range) =
80
+ contiguous_range_for_comment ( comment, & mut visited_comments)
81
+ {
82
+ res. push ( Fold { range, kind : FoldKind :: Comment } )
83
83
}
84
84
}
85
85
}
@@ -286,16 +286,18 @@ mod tests {
286
286
let ( ranges, text) = extract_tags ( ra_fixture, "fold" ) ;
287
287
288
288
let parse = SourceFile :: parse ( & text) ;
289
- let folds = folding_ranges ( & parse. tree ( ) ) ;
289
+ let mut folds = folding_ranges ( & parse. tree ( ) ) ;
290
+ folds. sort_by_key ( |fold| ( fold. range . start ( ) , fold. range . end ( ) ) ) ;
291
+
290
292
assert_eq ! (
291
293
folds. len( ) ,
292
294
ranges. len( ) ,
293
295
"The amount of folds is different than the expected amount"
294
296
) ;
295
297
296
298
for ( fold, ( range, attr) ) in folds. iter ( ) . zip ( ranges. into_iter ( ) ) {
297
- assert_eq ! ( fold. range. start( ) , range. start( ) ) ;
298
- assert_eq ! ( fold. range. end( ) , range. end( ) ) ;
299
+ assert_eq ! ( fold. range. start( ) , range. start( ) , "mismatched start of folding ranges" ) ;
300
+ assert_eq ! ( fold. range. end( ) , range. end( ) , "mismatched end of folding ranges" ) ;
299
301
300
302
let kind = match fold. kind {
301
303
FoldKind :: Comment => "comment" ,
@@ -525,7 +527,10 @@ const FOO: [usize; 4] = <fold array>[
525
527
// 1. some normal comment
526
528
<fold region>// region: test
527
529
// 2. some normal comment
528
- calling_function(x,y);
530
+ <fold region>// region: inner
531
+ fn f() {}
532
+ // endregion</fold>
533
+ fn f2() {}
529
534
// endregion: test</fold>
530
535
"# ,
531
536
)
0 commit comments