Merge pull request #20054 from Young-Flash/folding_all

feat: support folding multiline arg list & fn body in one folding range
This commit is contained in:
Shoyu Vanilla (Flint) 2025-07-10 12:05:31 +00:00 committed by GitHub
commit 600f573256
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 3 deletions

View File

@ -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",
};
@ -329,6 +360,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(
@ -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>
"#,
)
}

View File

@ -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);