about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShoyu Vanilla (Flint) <modulo641@gmail.com>2025-07-10 12:05:31 +0000
committerGitHub <noreply@github.com>2025-07-10 12:05:31 +0000
commitc1cf45a2f3a86fe32dd154bcabc1f0c363d5c411 (patch)
treec7e12286ea4e50c2bfe9855dff7642860daad43e
parent649ec27cedcf4cb1519b5d78978712a66ee270c0 (diff)
parent594252fdc4a3ec5a3db94df5a2f4697a63e61283 (diff)
downloadrust-c1cf45a2f3a86fe32dd154bcabc1f0c363d5c411.tar.gz
rust-c1cf45a2f3a86fe32dd154bcabc1f0c363d5c411.zip
Merge pull request #20054 from Young-Flash/folding_all
feat: support folding multiline arg list & fn body in one folding range
-rwxr-xr-xsrc/tools/rust-analyzer/crates/ide/src/folding_ranges.rs52
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs3
2 files changed, 52 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
index 9bd8504733a..c081796d078 100755
--- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
@@ -23,6 +23,7 @@ pub enum FoldKind {
     WhereClause,
     ReturnType,
     MatchArm,
+    Function,
     // region: item runs
     Modules,
     Consts,
@@ -47,6 +48,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
     let mut res = vec![];
     let mut visited_comments = FxHashSet::default();
     let mut visited_nodes = FxHashSet::default();
+    let mut merged_fn_bodies = FxHashSet::default();
 
     // regions can be nested, here is a LIFO buffer
     let mut region_starts: Vec<TextSize> = vec![];
@@ -59,6 +61,32 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
                 NodeOrToken::Token(token) => token.text().contains('\n'),
             };
             if is_multiline {
+                // for the func with multiline param list
+                if matches!(element.kind(), FN) {
+                    if let NodeOrToken::Node(node) = &element {
+                        if let Some(fn_node) = ast::Fn::cast(node.clone()) {
+                            if !fn_node
+                                .param_list()
+                                .map(|param_list| param_list.syntax().text().contains_char('\n'))
+                                .unwrap_or(false)
+                            {
+                                continue;
+                            }
+
+                            if let Some(body) = fn_node.body() {
+                                res.push(Fold {
+                                    range: TextRange::new(
+                                        node.text_range().start(),
+                                        node.text_range().end(),
+                                    ),
+                                    kind: FoldKind::Function,
+                                });
+                                merged_fn_bodies.insert(body.syntax().text_range());
+                                continue;
+                            }
+                        }
+                    }
+                }
                 res.push(Fold { range: element.text_range(), kind });
                 continue;
             }
@@ -152,6 +180,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
         ARG_LIST | PARAM_LIST | GENERIC_ARG_LIST | GENERIC_PARAM_LIST => Some(FoldKind::ArgList),
         ARRAY_EXPR => Some(FoldKind::Array),
         RET_TYPE => Some(FoldKind::ReturnType),
+        FN => Some(FoldKind::Function),
         WHERE_CLAUSE => Some(FoldKind::WhereClause),
         ASSOC_ITEM_LIST
         | RECORD_FIELD_LIST
@@ -291,6 +320,7 @@ mod tests {
 
     use super::*;
 
+    #[track_caller]
     fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
         let (ranges, text) = extract_tags(ra_fixture, "fold");
 
@@ -322,6 +352,7 @@ mod tests {
                 FoldKind::WhereClause => "whereclause",
                 FoldKind::ReturnType => "returntype",
                 FoldKind::MatchArm => "matcharm",
+                FoldKind::Function => "function",
                 FoldKind::TraitAliases => "traitaliases",
                 FoldKind::ExternCrates => "externcrates",
             };
@@ -330,6 +361,23 @@ mod tests {
     }
 
     #[test]
+    fn test_fold_func_with_multiline_param_list() {
+        check(
+            r#"
+<fold function>fn func<fold arglist>(
+    a: i32,
+    b: i32,
+    c: i32,
+)</fold> <fold block>{
+
+
+
+}</fold></fold>
+"#,
+        );
+    }
+
+    #[test]
     fn test_fold_comments() {
         check(
             r#"
@@ -541,10 +589,10 @@ const _: S = S <fold block>{
     fn fold_multiline_params() {
         check(
             r#"
-fn foo<fold arglist>(
+<fold function>fn foo<fold arglist>(
     x: i32,
     y: String,
-)</fold> {}
+)</fold> {}</fold>
 "#,
         )
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index 8a848fb848c..292be1d5315 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -911,7 +911,8 @@ pub(crate) fn folding_range(
         | FoldKind::Array
         | FoldKind::TraitAliases
         | FoldKind::ExternCrates
-        | FoldKind::MatchArm => None,
+        | FoldKind::MatchArm
+        | FoldKind::Function => None,
     };
 
     let range = range(line_index, fold.range);