@@ -23,6 +23,7 @@ pub enum FoldKind {
2323 WhereClause ,
2424 ReturnType ,
2525 MatchArm ,
26+ Function ,
2627 // region: item runs
2728 Modules ,
2829 Consts ,
@@ -47,6 +48,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
4748 let mut res = vec ! [ ] ;
4849 let mut visited_comments = FxHashSet :: default ( ) ;
4950 let mut visited_nodes = FxHashSet :: default ( ) ;
51+ let mut merged_fn_bodies = FxHashSet :: default ( ) ;
5052
5153 // regions can be nested, here is a LIFO buffer
5254 let mut region_starts: Vec < TextSize > = vec ! [ ] ;
@@ -59,6 +61,32 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
5961 NodeOrToken :: Token ( token) => token. text ( ) . contains ( '\n' ) ,
6062 } ;
6163 if is_multiline {
64+ // for the func with multiline param list
65+ if matches ! ( element. kind( ) , FN ) {
66+ if let NodeOrToken :: Node ( node) = & element {
67+ if let Some ( fn_node) = ast:: Fn :: cast ( node. clone ( ) ) {
68+ if !fn_node
69+ . param_list ( )
70+ . map ( |param_list| param_list. syntax ( ) . text ( ) . contains_char ( '\n' ) )
71+ . unwrap_or ( false )
72+ {
73+ continue ;
74+ }
75+
76+ if let Some ( body) = fn_node. body ( ) {
77+ res. push ( Fold {
78+ range : TextRange :: new (
79+ node. text_range ( ) . start ( ) ,
80+ node. text_range ( ) . end ( ) ,
81+ ) ,
82+ kind : FoldKind :: Function ,
83+ } ) ;
84+ merged_fn_bodies. insert ( body. syntax ( ) . text_range ( ) ) ;
85+ continue ;
86+ }
87+ }
88+ }
89+ }
6290 res. push ( Fold { range : element. text_range ( ) , kind } ) ;
6391 continue ;
6492 }
@@ -152,6 +180,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
152180 ARG_LIST | PARAM_LIST | GENERIC_ARG_LIST | GENERIC_PARAM_LIST => Some ( FoldKind :: ArgList ) ,
153181 ARRAY_EXPR => Some ( FoldKind :: Array ) ,
154182 RET_TYPE => Some ( FoldKind :: ReturnType ) ,
183+ FN => Some ( FoldKind :: Function ) ,
155184 WHERE_CLAUSE => Some ( FoldKind :: WhereClause ) ,
156185 ASSOC_ITEM_LIST
157186 | RECORD_FIELD_LIST
@@ -291,6 +320,7 @@ mod tests {
291320
292321 use super :: * ;
293322
323+ #[ track_caller]
294324 fn check ( #[ rust_analyzer:: rust_fixture] ra_fixture : & str ) {
295325 let ( ranges, text) = extract_tags ( ra_fixture, "fold" ) ;
296326
@@ -322,13 +352,31 @@ mod tests {
322352 FoldKind :: WhereClause => "whereclause" ,
323353 FoldKind :: ReturnType => "returntype" ,
324354 FoldKind :: MatchArm => "matcharm" ,
355+ FoldKind :: Function => "function" ,
325356 FoldKind :: TraitAliases => "traitaliases" ,
326357 FoldKind :: ExternCrates => "externcrates" ,
327358 } ;
328359 assert_eq ! ( kind, & attr. unwrap( ) ) ;
329360 }
330361 }
331362
363+ #[ test]
364+ fn test_fold_func_with_multiline_param_list ( ) {
365+ check (
366+ r#"
367+ <fold function>fn func<fold arglist>(
368+ a: i32,
369+ b: i32,
370+ c: i32,
371+ )</fold> <fold block>{
372+
373+
374+
375+ }</fold></fold>
376+ "# ,
377+ ) ;
378+ }
379+
332380 #[ test]
333381 fn test_fold_comments ( ) {
334382 check (
@@ -541,10 +589,10 @@ const _: S = S <fold block>{
541589 fn fold_multiline_params ( ) {
542590 check (
543591 r#"
544- fn foo<fold arglist>(
592+ <fold function> fn foo<fold arglist>(
545593 x: i32,
546594 y: String,
547- )</fold> {}
595+ )</fold> {}</fold>
548596"# ,
549597 )
550598 }
0 commit comments