@@ -2,7 +2,7 @@ use ide_db::{FxHashSet, syntax_helpers::node_ext::vis_eq};
2
2
use syntax:: {
3
3
Direction , NodeOrToken , SourceFile ,
4
4
SyntaxKind :: { self , * } ,
5
- TextRange , TextSize ,
5
+ SyntaxNode , TextRange , TextSize ,
6
6
ast:: { self , AstNode , AstToken } ,
7
7
match_ast,
8
8
} ;
@@ -16,16 +16,21 @@ const REGION_END: &str = "// endregion";
16
16
pub enum FoldKind {
17
17
Comment ,
18
18
Imports ,
19
- Mods ,
19
+ Region ,
20
20
Block ,
21
21
ArgList ,
22
- Region ,
23
- Consts ,
24
- Statics ,
25
22
Array ,
26
23
WhereClause ,
27
24
ReturnType ,
28
25
MatchArm ,
26
+ // region: item runs
27
+ Modules ,
28
+ Consts ,
29
+ Statics ,
30
+ TypeAliases ,
31
+ TraitAliases ,
32
+ ExternCrates ,
33
+ // endregion: item runs
29
34
}
30
35
31
36
#[ derive( Debug ) ]
@@ -41,10 +46,7 @@ pub struct Fold {
41
46
pub ( crate ) fn folding_ranges ( file : & SourceFile ) -> Vec < Fold > {
42
47
let mut res = vec ! [ ] ;
43
48
let mut visited_comments = FxHashSet :: default ( ) ;
44
- let mut visited_imports = FxHashSet :: default ( ) ;
45
- let mut visited_mods = FxHashSet :: default ( ) ;
46
- let mut visited_consts = FxHashSet :: default ( ) ;
47
- let mut visited_statics = FxHashSet :: default ( ) ;
49
+ let mut visited_nodes = FxHashSet :: default ( ) ;
48
50
49
51
// regions can be nested, here is a LIFO buffer
50
52
let mut region_starts: Vec < TextSize > = vec ! [ ] ;
@@ -93,30 +95,40 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
93
95
if module. item_list( ) . is_none( ) {
94
96
if let Some ( range) = contiguous_range_for_item_group(
95
97
module,
96
- & mut visited_mods ,
98
+ & mut visited_nodes ,
97
99
) {
98
- res. push( Fold { range, kind: FoldKind :: Mods } )
100
+ res. push( Fold { range, kind: FoldKind :: Modules } )
99
101
}
100
102
}
101
103
} ,
102
104
ast:: Use ( use_) => {
103
- if let Some ( range) = contiguous_range_for_item_group( use_, & mut visited_imports ) {
105
+ if let Some ( range) = contiguous_range_for_item_group( use_, & mut visited_nodes ) {
104
106
res. push( Fold { range, kind: FoldKind :: Imports } )
105
107
}
106
108
} ,
107
109
ast:: Const ( konst) => {
108
- if let Some ( range) = contiguous_range_for_item_group( konst, & mut visited_consts ) {
110
+ if let Some ( range) = contiguous_range_for_item_group( konst, & mut visited_nodes ) {
109
111
res. push( Fold { range, kind: FoldKind :: Consts } )
110
112
}
111
113
} ,
112
114
ast:: Static ( statik) => {
113
- if let Some ( range) = contiguous_range_for_item_group( statik, & mut visited_statics ) {
115
+ if let Some ( range) = contiguous_range_for_item_group( statik, & mut visited_nodes ) {
114
116
res. push( Fold { range, kind: FoldKind :: Statics } )
115
117
}
116
118
} ,
117
- ast:: WhereClause ( where_clause) => {
118
- if let Some ( range) = fold_range_for_where_clause( where_clause) {
119
- res. push( Fold { range, kind: FoldKind :: WhereClause } )
119
+ ast:: TypeAlias ( alias) => {
120
+ if let Some ( range) = contiguous_range_for_item_group( alias, & mut visited_nodes) {
121
+ res. push( Fold { range, kind: FoldKind :: TypeAliases } )
122
+ }
123
+ } ,
124
+ ast:: TraitAlias ( alias) => {
125
+ if let Some ( range) = contiguous_range_for_item_group( alias, & mut visited_nodes) {
126
+ res. push( Fold { range, kind: FoldKind :: TraitAliases } )
127
+ }
128
+ } ,
129
+ ast:: ExternCrate ( extern_crate) => {
130
+ if let Some ( range) = contiguous_range_for_item_group( extern_crate, & mut visited_nodes) {
131
+ res. push( Fold { range, kind: FoldKind :: ExternCrates } )
120
132
}
121
133
} ,
122
134
ast:: MatchArm ( match_arm) => {
@@ -137,9 +149,10 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
137
149
fn fold_kind ( kind : SyntaxKind ) -> Option < FoldKind > {
138
150
match kind {
139
151
COMMENT => Some ( FoldKind :: Comment ) ,
140
- ARG_LIST | PARAM_LIST => Some ( FoldKind :: ArgList ) ,
152
+ ARG_LIST | PARAM_LIST | GENERIC_ARG_LIST | GENERIC_PARAM_LIST => Some ( FoldKind :: ArgList ) ,
141
153
ARRAY_EXPR => Some ( FoldKind :: Array ) ,
142
154
RET_TYPE => Some ( FoldKind :: ReturnType ) ,
155
+ WHERE_CLAUSE => Some ( FoldKind :: WhereClause ) ,
143
156
ASSOC_ITEM_LIST
144
157
| RECORD_FIELD_LIST
145
158
| RECORD_PAT_FIELD_LIST
@@ -155,11 +168,14 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
155
168
}
156
169
}
157
170
158
- fn contiguous_range_for_item_group < N > ( first : N , visited : & mut FxHashSet < N > ) -> Option < TextRange >
171
+ fn contiguous_range_for_item_group < N > (
172
+ first : N ,
173
+ visited : & mut FxHashSet < SyntaxNode > ,
174
+ ) -> Option < TextRange >
159
175
where
160
176
N : ast:: HasVisibility + Clone + Hash + Eq ,
161
177
{
162
- if !visited. insert ( first. clone ( ) ) {
178
+ if !visited. insert ( first. syntax ( ) . clone ( ) ) {
163
179
return None ;
164
180
}
165
181
@@ -183,7 +199,7 @@ where
183
199
if let Some ( next) = N :: cast ( node) {
184
200
let next_vis = next. visibility ( ) ;
185
201
if eq_visibility ( next_vis. clone ( ) , last_vis) {
186
- visited. insert ( next. clone ( ) ) ;
202
+ visited. insert ( next. syntax ( ) . clone ( ) ) ;
187
203
last_vis = next_vis;
188
204
last = next;
189
205
continue ;
@@ -259,18 +275,6 @@ fn contiguous_range_for_comment(
259
275
}
260
276
}
261
277
262
- fn fold_range_for_where_clause ( where_clause : ast:: WhereClause ) -> Option < TextRange > {
263
- let first_where_pred = where_clause. predicates ( ) . next ( ) ;
264
- let last_where_pred = where_clause. predicates ( ) . last ( ) ;
265
-
266
- if first_where_pred != last_where_pred {
267
- let start = where_clause. where_token ( ) ?. text_range ( ) . end ( ) ;
268
- let end = where_clause. syntax ( ) . text_range ( ) . end ( ) ;
269
- return Some ( TextRange :: new ( start, end) ) ;
270
- }
271
- None
272
- }
273
-
274
278
fn fold_range_for_multiline_match_arm ( match_arm : ast:: MatchArm ) -> Option < TextRange > {
275
279
if fold_kind ( match_arm. expr ( ) ?. syntax ( ) . kind ( ) ) . is_some ( ) {
276
280
None
@@ -307,16 +311,19 @@ mod tests {
307
311
let kind = match fold. kind {
308
312
FoldKind :: Comment => "comment" ,
309
313
FoldKind :: Imports => "imports" ,
310
- FoldKind :: Mods => "mods" ,
314
+ FoldKind :: Modules => "mods" ,
311
315
FoldKind :: Block => "block" ,
312
316
FoldKind :: ArgList => "arglist" ,
313
317
FoldKind :: Region => "region" ,
314
318
FoldKind :: Consts => "consts" ,
315
319
FoldKind :: Statics => "statics" ,
320
+ FoldKind :: TypeAliases => "typealiases" ,
316
321
FoldKind :: Array => "array" ,
317
322
FoldKind :: WhereClause => "whereclause" ,
318
323
FoldKind :: ReturnType => "returntype" ,
319
324
FoldKind :: MatchArm => "matcharm" ,
325
+ FoldKind :: TraitAliases => "traitaliases" ,
326
+ FoldKind :: ExternCrates => "externcrates" ,
320
327
} ;
321
328
assert_eq ! ( kind, & attr. unwrap( ) ) ;
322
329
}
@@ -594,19 +601,18 @@ static SECOND_STATIC: &str = "second";</fold>
594
601
595
602
#[ test]
596
603
fn fold_where_clause ( ) {
597
- // fold multi-line and don't fold single line.
598
604
check (
599
605
r#"
600
606
fn foo()
601
- where <fold whereclause>
607
+ <fold whereclause>where
602
608
A: Foo,
603
609
B: Foo,
604
610
C: Foo,
605
611
D: Foo,</fold> {}
606
612
607
613
fn bar()
608
- where
609
- A: Bar, {}
614
+ <fold whereclause> where
615
+ A: Bar,</fold> {}
610
616
"# ,
611
617
)
612
618
}
@@ -621,6 +627,18 @@ fn foo()<fold returntype>-> (
621
627
)</fold> { (true, true) }
622
628
623
629
fn bar() -> (bool, bool) { (true, true) }
630
+ "# ,
631
+ )
632
+ }
633
+
634
+ #[ test]
635
+ fn fold_generics ( ) {
636
+ check (
637
+ r#"
638
+ type Foo<T, U> = foo<fold arglist><
639
+ T,
640
+ U,
641
+ ></fold>;
624
642
"# ,
625
643
)
626
644
}
0 commit comments