aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/folding_ranges.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs
index 2b9ed123c..e03ddaa14 100644
--- a/crates/ide/src/folding_ranges.rs
+++ b/crates/ide/src/folding_ranges.rs
@@ -20,6 +20,7 @@ pub enum FoldKind {
20 Consts, 20 Consts,
21 Statics, 21 Statics,
22 Array, 22 Array,
23 WhereClause,
23} 24}
24 25
25#[derive(Debug)] 26#[derive(Debug)]
@@ -35,6 +36,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
35 let mut visited_mods = FxHashSet::default(); 36 let mut visited_mods = FxHashSet::default();
36 let mut visited_consts = FxHashSet::default(); 37 let mut visited_consts = FxHashSet::default();
37 let mut visited_statics = FxHashSet::default(); 38 let mut visited_statics = FxHashSet::default();
39 let mut visited_where_clauses = FxHashSet::default();
38 // regions can be nested, here is a LIFO buffer 40 // regions can be nested, here is a LIFO buffer
39 let mut regions_starts: Vec<TextSize> = vec![]; 41 let mut regions_starts: Vec<TextSize> = vec![];
40 42
@@ -109,6 +111,15 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
109 res.push(Fold { range, kind: FoldKind::Statics }) 111 res.push(Fold { range, kind: FoldKind::Statics })
110 } 112 }
111 } 113 }
114
115 // Fold where clause
116 if node.kind() == WHERE_CLAUSE && !visited_where_clauses.contains(&node) {
117 if let Some(range) =
118 contiguous_range_for_where(&node, &mut visited_where_clauses)
119 {
120 res.push(Fold { range, kind: FoldKind::WhereClause })
121 }
122 }
112 } 123 }
113 } 124 }
114 } 125 }
@@ -241,6 +252,28 @@ fn contiguous_range_for_comment(
241 } 252 }
242} 253}
243 254
255fn contiguous_range_for_where(
256 node: &SyntaxNode,
257 visited: &mut FxHashSet<SyntaxNode>,
258) -> Option<TextRange> {
259 let first_where_pred = node.first_child();
260 let last_where_pred = node.last_child();
261
262 if first_where_pred != last_where_pred {
263 let mut it = node.descendants_with_tokens();
264 if let (Some(_where_clause), Some(where_kw), Some(last_comma)) =
265 (it.next(), it.next(), it.last())
266 {
267 let start = where_kw.text_range().end();
268 let end = last_comma.text_range().end();
269
270 visited.insert(node.clone());
271 return Some(TextRange::new(start, end));
272 }
273 }
274 None
275}
276
244#[cfg(test)] 277#[cfg(test)]
245mod tests { 278mod tests {
246 use test_utils::extract_tags; 279 use test_utils::extract_tags;
@@ -272,6 +305,7 @@ mod tests {
272 FoldKind::Consts => "consts", 305 FoldKind::Consts => "consts",
273 FoldKind::Statics => "statics", 306 FoldKind::Statics => "statics",
274 FoldKind::Array => "array", 307 FoldKind::Array => "array",
308 FoldKind::WhereClause => "whereclause",
275 }; 309 };
276 assert_eq!(kind, &attr.unwrap()); 310 assert_eq!(kind, &attr.unwrap());
277 } 311 }
@@ -513,4 +547,23 @@ static SECOND_STATIC: &str = "second";</fold>
513 "#, 547 "#,
514 ) 548 )
515 } 549 }
550
551 #[test]
552 fn fold_where_clause() {
553 // fold multi-line and don't fold single line.
554 check(
555 r#"
556fn foo()
557where<fold whereclause>
558 A: Foo,
559 B: Foo,
560 C: Foo,
561 D: Foo,</fold> {}
562
563fn bar()
564where
565 A: Bar, {}
566"#,
567 )
568 }
516} 569}