diff options
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r-- | crates/ra_editor/src/folding_ranges.rs | 86 | ||||
-rw-r--r-- | crates/ra_editor/src/lib.rs | 2 |
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 @@ | |||
1 | use std::collections::HashSet; | ||
2 | |||
3 | use ra_syntax::{ | ||
4 | File, TextRange, SyntaxNodeRef, | ||
5 | SyntaxKind, | ||
6 | algo::{walk, Direction, siblings}, | ||
7 | }; | ||
8 | |||
9 | pub enum FoldKind { | ||
10 | Comment, | ||
11 | Imports, | ||
12 | } | ||
13 | |||
14 | pub struct Fold { | ||
15 | pub range: TextRange, | ||
16 | pub kind: FoldKind, | ||
17 | } | ||
18 | |||
19 | pub 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 | |||
56 | fn 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; | |||
10 | mod symbols; | 10 | mod symbols; |
11 | mod line_index; | 11 | mod line_index; |
12 | mod edit; | 12 | mod edit; |
13 | mod folding_ranges; | ||
13 | mod code_actions; | 14 | mod code_actions; |
14 | mod typing; | 15 | mod typing; |
15 | mod completion; | 16 | mod 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)] |