From ff0a706a30567f297642ba1fa6ee9537ed82c40f Mon Sep 17 00:00:00 2001 From: "Jeremy A. Kolb" Date: Mon, 24 Sep 2018 09:52:33 -0400 Subject: Split folding ranges into editor and lsp parts --- crates/ra_editor/src/folding_ranges.rs | 86 ++++++++++++++++++++++++++++++++++ crates/ra_editor/src/lib.rs | 2 + 2 files changed, 88 insertions(+) create mode 100644 crates/ra_editor/src/folding_ranges.rs (limited to 'crates/ra_editor/src') 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 @@ +use std::collections::HashSet; + +use ra_syntax::{ + File, TextRange, SyntaxNodeRef, + SyntaxKind, + algo::{walk, Direction, siblings}, +}; + +pub enum FoldKind { + Comment, + Imports, +} + +pub struct Fold { + pub range: TextRange, + pub kind: FoldKind, +} + +pub fn folding_ranges(file: &File) -> Vec { + let syntax = file.syntax(); + + let mut res = vec![]; + let mut visited = HashSet::new(); + + for node in walk::preorder(syntax) { + if visited.contains(&node) { + continue; + } + + let range_and_kind = match node.kind() { + SyntaxKind::COMMENT => ( + contiguous_range_for(SyntaxKind::COMMENT, node, &mut visited), + Some(FoldKind::Comment), + ), + SyntaxKind::USE_ITEM => ( + contiguous_range_for(SyntaxKind::USE_ITEM, node, &mut visited), + Some(FoldKind::Imports), + ), + _ => (None, None), + }; + + match range_and_kind { + (Some(range), Some(kind)) => { + res.push(Fold { + range: range, + kind: kind + }); + } + _ => {} + } + } + + res +} + +fn contiguous_range_for<'a>( + kind: SyntaxKind, + node: SyntaxNodeRef<'a>, + visited: &mut HashSet>, +) -> Option { + visited.insert(node); + + let left = node; + let mut right = node; + for node in siblings(node, Direction::Forward) { + visited.insert(node); + match node.kind() { + SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), + k => { + if k == kind { + right = node + } else { + break; + } + } + } + } + if left != right { + Some(TextRange::from_to( + left.range().start(), + right.range().end(), + )) + } else { + None + } +} \ 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; mod symbols; mod line_index; mod edit; +mod folding_ranges; mod code_actions; mod typing; mod completion; @@ -36,6 +37,7 @@ pub use self::{ }, typing::{join_lines, on_eq_typed}, completion::{scope_completion, CompletionItem}, + folding_ranges::{Fold, FoldKind, folding_ranges} }; #[derive(Debug)] -- cgit v1.2.3