about summary refs log tree commit diff
diff options
context:
space:
mode:
authorm5tfi <72708423+m5tfi@users.noreply.github.com>2021-04-30 10:18:36 +0200
committerm5tfi <72708423+m5tfi@users.noreply.github.com>2021-04-30 10:18:36 +0200
commit5778ab1e41b48371cf3100a397a138deda3f73f5 (patch)
treed82b384b5e70086c532d0dea4a77b61dba412d1f
parent80bee14e14f67f02746befff77a8a4bbfd3e5849 (diff)
downloadrust-5778ab1e41b48371cf3100a397a138deda3f73f5.tar.gz
rust-5778ab1e41b48371cf3100a397a138deda3f73f5.zip
add folding for where clauses
-rw-r--r--crates/ide/src/folding_ranges.rs53
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
2 files changed, 54 insertions, 0 deletions
diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs
index 2b9ed123c11..e03ddaa14f3 100644
--- a/crates/ide/src/folding_ranges.rs
+++ b/crates/ide/src/folding_ranges.rs
@@ -20,6 +20,7 @@ pub enum FoldKind {
     Consts,
     Statics,
     Array,
+    WhereClause,
 }
 
 #[derive(Debug)]
@@ -35,6 +36,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
     let mut visited_mods = FxHashSet::default();
     let mut visited_consts = FxHashSet::default();
     let mut visited_statics = FxHashSet::default();
+    let mut visited_where_clauses = FxHashSet::default();
     // regions can be nested, here is a LIFO buffer
     let mut regions_starts: Vec<TextSize> = vec![];
 
@@ -109,6 +111,15 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
                         res.push(Fold { range, kind: FoldKind::Statics })
                     }
                 }
+
+                // Fold where clause
+                if node.kind() == WHERE_CLAUSE && !visited_where_clauses.contains(&node) {
+                    if let Some(range) =
+                        contiguous_range_for_where(&node, &mut visited_where_clauses)
+                    {
+                        res.push(Fold { range, kind: FoldKind::WhereClause })
+                    }
+                }
             }
         }
     }
@@ -241,6 +252,28 @@ fn contiguous_range_for_comment(
     }
 }
 
+fn contiguous_range_for_where(
+    node: &SyntaxNode,
+    visited: &mut FxHashSet<SyntaxNode>,
+) -> Option<TextRange> {
+    let first_where_pred = node.first_child();
+    let last_where_pred = node.last_child();
+
+    if first_where_pred != last_where_pred {
+        let mut it = node.descendants_with_tokens();
+        if let (Some(_where_clause), Some(where_kw), Some(last_comma)) =
+            (it.next(), it.next(), it.last())
+        {
+            let start = where_kw.text_range().end();
+            let end = last_comma.text_range().end();
+
+            visited.insert(node.clone());
+            return Some(TextRange::new(start, end));
+        }
+    }
+    None
+}
+
 #[cfg(test)]
 mod tests {
     use test_utils::extract_tags;
@@ -272,6 +305,7 @@ mod tests {
                 FoldKind::Consts => "consts",
                 FoldKind::Statics => "statics",
                 FoldKind::Array => "array",
+                FoldKind::WhereClause => "whereclause",
             };
             assert_eq!(kind, &attr.unwrap());
         }
@@ -513,4 +547,23 @@ static SECOND_STATIC: &str = "second";</fold>
             "#,
         )
     }
+
+    #[test]
+    fn fold_where_clause() {
+        // fold multi-line and don't fold single line.
+        check(
+            r#"
+fn foo()
+where<fold whereclause>
+    A: Foo,
+    B: Foo,
+    C: Foo,
+    D: Foo,</fold> {}
+
+fn bar()
+where
+    A: Bar, {}
+"#,
+        )
+    }
 }
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index c2361b32e73..5eff036ecfa 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -524,6 +524,7 @@ pub(crate) fn folding_range(
         | FoldKind::ArgList
         | FoldKind::Consts
         | FoldKind::Statics
+        | FoldKind::WhereClause
         | FoldKind::Array => None,
     };