@@ -26,6 +26,8 @@ pub enum FoldKind {
2626 WhereClause ,
2727 ReturnType ,
2828 MatchArm ,
29+ Stmt ,
30+ TailExpr ,
2931}
3032
3133#[ derive( Debug ) ]
@@ -124,6 +126,11 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
124126 res. push( Fold { range, kind: FoldKind :: MatchArm } )
125127 }
126128 } ,
129+ ast:: Expr ( expr) => {
130+ if let Some ( range) = fold_range_for_multiline_tail_expr( expr) {
131+ res. push( Fold { range, kind: FoldKind :: TailExpr } )
132+ }
133+ } ,
127134 _ => ( ) ,
128135 }
129136 }
@@ -151,6 +158,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
151158 | MATCH_ARM_LIST
152159 | VARIANT_LIST
153160 | TOKEN_TREE => Some ( FoldKind :: Block ) ,
161+ EXPR_STMT | LET_STMT => Some ( FoldKind :: Stmt ) ,
154162 _ => None ,
155163 }
156164}
@@ -281,6 +289,18 @@ fn fold_range_for_multiline_match_arm(match_arm: ast::MatchArm) -> Option<TextRa
281289 }
282290}
283291
292+ fn fold_range_for_multiline_tail_expr ( expr : ast:: Expr ) -> Option < TextRange > {
293+ let stmt_list = ast:: StmtList :: cast ( expr. syntax ( ) . parent ( ) ?) ?;
294+ let tail_expr = stmt_list. tail_expr ( ) ?;
295+
296+ // Only fold if the tail expression spans multiple lines
297+ if tail_expr. syntax ( ) . text ( ) . contains_char ( '\n' ) {
298+ Some ( tail_expr. syntax ( ) . text_range ( ) )
299+ } else {
300+ None
301+ }
302+ }
303+
284304#[ cfg( test) ]
285305mod tests {
286306 use test_utils:: extract_tags;
@@ -317,6 +337,8 @@ mod tests {
317337 FoldKind :: WhereClause => "whereclause" ,
318338 FoldKind :: ReturnType => "returntype" ,
319339 FoldKind :: MatchArm => "matcharm" ,
340+ FoldKind :: Stmt => "stmt" ,
341+ FoldKind :: TailExpr => "tailexpr" ,
320342 } ;
321343 assert_eq ! ( kind, & attr. unwrap( ) ) ;
322344 }
@@ -465,10 +487,10 @@ macro_rules! foo <fold block>{
465487 check (
466488 r#"
467489fn main() <fold block>{
468- match 0 <fold block>{
490+ <fold tailexpr> match 0 <fold block>{
469491 0 => 0,
470492 _ => 1,
471- }</fold>
493+ }</fold></fold>
472494}</fold>
473495"# ,
474496 ) ;
@@ -479,7 +501,7 @@ fn main() <fold block>{
479501 check (
480502 r#"
481503 fn main() <fold block>{
482- match foo <fold block>{
504+ <fold tailexpr> match foo <fold block>{
483505 block => <fold block>{
484506 }</fold>,
485507 matcharm => <fold matcharm>some.
@@ -498,7 +520,7 @@ fn main() <fold block>{
498520 structS => <fold matcharm>StructS <fold block>{
499521 a: 31,
500522 }</fold></fold>,
501- }</fold>
523+ }</fold></fold>
502524 }</fold>
503525 "# ,
504526 )
@@ -509,11 +531,11 @@ fn main() <fold block>{
509531 check (
510532 r#"
511533fn main() <fold block>{
512- frobnicate<fold arglist>(
534+ <fold tailexpr> frobnicate<fold arglist>(
513535 1,
514536 2,
515537 3,
516- )</fold>
538+ )</fold></fold>
517539}</fold>
518540"# ,
519541 )
@@ -621,6 +643,37 @@ fn foo()<fold returntype>-> (
621643)</fold> { (true, true) }
622644
623645fn bar() -> (bool, bool) { (true, true) }
646+ "# ,
647+ )
648+ }
649+
650+ #[ test]
651+ fn test_fold_tail_expr ( ) {
652+ check (
653+ r#"
654+ fn f() <fold block>{
655+ let x = 1;
656+
657+ <fold tailexpr>some_function()
658+ .chain()
659+ .method()</fold>
660+ }</fold>
661+ "# ,
662+ )
663+ }
664+
665+ #[ test]
666+ fn test_fold_let_stmt_with_chained_methods ( ) {
667+ check (
668+ r#"
669+ fn main() <fold block>{
670+ <fold stmt>let result = some_value
671+ .method1()
672+ .method2()
673+ .method3();</fold>
674+
675+ println!("{}", result);
676+ }</fold>
624677"# ,
625678 )
626679 }
0 commit comments