@@ -2,7 +2,7 @@ use ide_db::{FxHashSet, syntax_helpers::node_ext::vis_eq};
22use syntax:: {
33 Direction , NodeOrToken , SourceFile ,
44 SyntaxKind :: { self , * } ,
5- TextRange , TextSize ,
5+ SyntaxNode , TextRange , TextSize ,
66 ast:: { self , AstNode , AstToken } ,
77 match_ast,
88} ;
@@ -16,16 +16,21 @@ const REGION_END: &str = "// endregion";
1616pub enum FoldKind {
1717 Comment ,
1818 Imports ,
19- Mods ,
19+ Region ,
2020 Block ,
2121 ArgList ,
22- Region ,
23- Consts ,
24- Statics ,
2522 Array ,
2623 WhereClause ,
2724 ReturnType ,
2825 MatchArm ,
26+ // region: item runs
27+ Modules ,
28+ Consts ,
29+ Statics ,
30+ TypeAliases ,
31+ TraitAliases ,
32+ ExternCrates ,
33+ // endregion: item runs
2934}
3035
3136#[ derive( Debug ) ]
@@ -41,10 +46,7 @@ pub struct Fold {
4146pub ( crate ) fn folding_ranges ( file : & SourceFile ) -> Vec < Fold > {
4247 let mut res = vec ! [ ] ;
4348 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 ( ) ;
4850
4951 // regions can be nested, here is a LIFO buffer
5052 let mut region_starts: Vec < TextSize > = vec ! [ ] ;
@@ -93,30 +95,40 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
9395 if module. item_list( ) . is_none( ) {
9496 if let Some ( range) = contiguous_range_for_item_group(
9597 module,
96- & mut visited_mods ,
98+ & mut visited_nodes ,
9799 ) {
98- res. push( Fold { range, kind: FoldKind :: Mods } )
100+ res. push( Fold { range, kind: FoldKind :: Modules } )
99101 }
100102 }
101103 } ,
102104 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 ) {
104106 res. push( Fold { range, kind: FoldKind :: Imports } )
105107 }
106108 } ,
107109 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 ) {
109111 res. push( Fold { range, kind: FoldKind :: Consts } )
110112 }
111113 } ,
112114 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 ) {
114116 res. push( Fold { range, kind: FoldKind :: Statics } )
115117 }
116118 } ,
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 } )
120132 }
121133 } ,
122134 ast:: MatchArm ( match_arm) => {
@@ -137,9 +149,10 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
137149fn fold_kind ( kind : SyntaxKind ) -> Option < FoldKind > {
138150 match kind {
139151 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 ) ,
141153 ARRAY_EXPR => Some ( FoldKind :: Array ) ,
142154 RET_TYPE => Some ( FoldKind :: ReturnType ) ,
155+ WHERE_CLAUSE => Some ( FoldKind :: WhereClause ) ,
143156 ASSOC_ITEM_LIST
144157 | RECORD_FIELD_LIST
145158 | RECORD_PAT_FIELD_LIST
@@ -155,11 +168,14 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
155168 }
156169}
157170
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 >
159175where
160176 N : ast:: HasVisibility + Clone + Hash + Eq ,
161177{
162- if !visited. insert ( first. clone ( ) ) {
178+ if !visited. insert ( first. syntax ( ) . clone ( ) ) {
163179 return None ;
164180 }
165181
@@ -183,7 +199,7 @@ where
183199 if let Some ( next) = N :: cast ( node) {
184200 let next_vis = next. visibility ( ) ;
185201 if eq_visibility ( next_vis. clone ( ) , last_vis) {
186- visited. insert ( next. clone ( ) ) ;
202+ visited. insert ( next. syntax ( ) . clone ( ) ) ;
187203 last_vis = next_vis;
188204 last = next;
189205 continue ;
@@ -259,18 +275,6 @@ fn contiguous_range_for_comment(
259275 }
260276}
261277
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-
274278fn fold_range_for_multiline_match_arm ( match_arm : ast:: MatchArm ) -> Option < TextRange > {
275279 if fold_kind ( match_arm. expr ( ) ?. syntax ( ) . kind ( ) ) . is_some ( ) {
276280 None
@@ -307,16 +311,19 @@ mod tests {
307311 let kind = match fold. kind {
308312 FoldKind :: Comment => "comment" ,
309313 FoldKind :: Imports => "imports" ,
310- FoldKind :: Mods => "mods" ,
314+ FoldKind :: Modules => "mods" ,
311315 FoldKind :: Block => "block" ,
312316 FoldKind :: ArgList => "arglist" ,
313317 FoldKind :: Region => "region" ,
314318 FoldKind :: Consts => "consts" ,
315319 FoldKind :: Statics => "statics" ,
320+ FoldKind :: TypeAliases => "typealiases" ,
316321 FoldKind :: Array => "array" ,
317322 FoldKind :: WhereClause => "whereclause" ,
318323 FoldKind :: ReturnType => "returntype" ,
319324 FoldKind :: MatchArm => "matcharm" ,
325+ FoldKind :: TraitAliases => "traitaliases" ,
326+ FoldKind :: ExternCrates => "externcrates" ,
320327 } ;
321328 assert_eq ! ( kind, & attr. unwrap( ) ) ;
322329 }
@@ -594,19 +601,18 @@ static SECOND_STATIC: &str = "second";</fold>
594601
595602 #[ test]
596603 fn fold_where_clause ( ) {
597- // fold multi-line and don't fold single line.
598604 check (
599605 r#"
600606fn foo()
601- where <fold whereclause>
607+ <fold whereclause>where
602608 A: Foo,
603609 B: Foo,
604610 C: Foo,
605611 D: Foo,</fold> {}
606612
607613fn bar()
608- where
609- A: Bar, {}
614+ <fold whereclause> where
615+ A: Bar,</fold> {}
610616"# ,
611617 )
612618 }
@@ -621,6 +627,18 @@ fn foo()<fold returntype>-> (
621627)</fold> { (true, true) }
622628
623629fn 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>;
624642"# ,
625643 )
626644 }
0 commit comments