aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r--crates/ra_editor/src/folding_ranges.rs86
-rw-r--r--crates/ra_editor/src/lib.rs2
2 files changed, 88 insertions, 0 deletions
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs
new file mode 100644
index 000000000..4518e8d24
--- /dev/null
+++ b/crates/ra_editor/src/folding_ranges.rs
@@ -0,0 +1,86 @@
1use std::collections::HashSet;
2
3use ra_syntax::{
4 File, TextRange, SyntaxNodeRef,
5 SyntaxKind,
6 algo::{walk, Direction, siblings},
7};
8
9pub enum FoldKind {
10 Comment,
11 Imports,
12}
13
14pub struct Fold {
15 pub range: TextRange,
16 pub kind: FoldKind,
17}
18
19pub fn folding_ranges(file: &File) -> Vec<Fold> {
20 let syntax = file.syntax();
21
22 let mut res = vec![];
23 let mut visited = HashSet::new();
24
25 for node in walk::preorder(syntax) {
26 if visited.contains(&node) {
27 continue;
28 }
29
30 let range_and_kind = match node.kind() {
31 SyntaxKind::COMMENT => (
32 contiguous_range_for(SyntaxKind::COMMENT, node, &mut visited),
33 Some(FoldKind::Comment),
34 ),
35 SyntaxKind::USE_ITEM => (
36 contiguous_range_for(SyntaxKind::USE_ITEM, node, &mut visited),
37 Some(FoldKind::Imports),
38 ),
39 _ => (None, None),
40 };
41
42 match range_and_kind {
43 (Some(range), Some(kind)) => {
44 res.push(Fold {
45 range: range,
46 kind: kind
47 });
48 }
49 _ => {}
50 }
51 }
52
53 res
54}
55
56fn contiguous_range_for<'a>(
57 kind: SyntaxKind,
58 node: SyntaxNodeRef<'a>,
59 visited: &mut HashSet<SyntaxNodeRef<'a>>,
60) -> Option<TextRange> {
61 visited.insert(node);
62
63 let left = node;
64 let mut right = node;
65 for node in siblings(node, Direction::Forward) {
66 visited.insert(node);
67 match node.kind() {
68 SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
69 k => {
70 if k == kind {
71 right = node
72 } else {
73 break;
74 }
75 }
76 }
77 }
78 if left != right {
79 Some(TextRange::from_to(
80 left.range().start(),
81 right.range().end(),
82 ))
83 } else {
84 None
85 }
86} \ No newline at end of file
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index 78ed34c7c..de929d73a 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -10,6 +10,7 @@ mod extend_selection;
10mod symbols; 10mod symbols;
11mod line_index; 11mod line_index;
12mod edit; 12mod edit;
13mod folding_ranges;
13mod code_actions; 14mod code_actions;
14mod typing; 15mod typing;
15mod completion; 16mod completion;
@@ -36,6 +37,7 @@ pub use self::{
36 }, 37 },
37 typing::{join_lines, on_eq_typed}, 38 typing::{join_lines, on_eq_typed},
38 completion::{scope_completion, CompletionItem}, 39 completion::{scope_completion, CompletionItem},
40 folding_ranges::{Fold, FoldKind, folding_ranges}
39}; 41};
40 42
41#[derive(Debug)] 43#[derive(Debug)]