From ff0a706a30567f297642ba1fa6ee9537ed82c40f Mon Sep 17 00:00:00 2001 From: "Jeremy A. Kolb" Date: Mon, 24 Sep 2018 09:52:33 -0400 Subject: [PATCH] Split folding ranges into editor and lsp parts --- crates/ra_analysis/src/lib.rs | 5 + crates/ra_editor/src/folding_ranges.rs | 86 ++++++++++++++++ crates/ra_editor/src/lib.rs | 2 + .../ra_lsp_server/src/main_loop/handlers.rs | 98 ++++--------------- 4 files changed, 114 insertions(+), 77 deletions(-) create mode 100644 crates/ra_editor/src/folding_ranges.rs diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 4da55ab269..b4c7db476b 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -34,6 +34,7 @@ use imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; pub use ra_editor::{ StructureNode, LineIndex, FileSymbol, Runnable, RunnableKind, HighlightedRange, CompletionItem, + Fold, FoldKind }; pub use job::{JobToken, JobHandle}; @@ -224,6 +225,10 @@ impl Analysis { pub fn diagnostics(&self, file_id: FileId) -> Vec { self.imp.diagnostics(file_id) } + pub fn folding_ranges(&self, file_id: FileId) -> Vec { + let file = self.imp.file_syntax(file_id); + ra_editor::folding_ranges(&file) + } } #[derive(Debug)] diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs new file mode 100644 index 0000000000..4518e8d24d --- /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 78ed34c7c1..de929d73a6 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)] diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 36cdeda380..51061543c2 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap}; use languageserver_types::{ Diagnostic, DiagnosticSeverity, DocumentSymbol, @@ -8,11 +8,9 @@ use languageserver_types::{ FoldingRange, FoldingRangeParams, FoldingRangeKind }; use serde_json::to_value; -use ra_analysis::{Query, FileId, RunnableKind, JobToken}; +use ra_analysis::{Query, FileId, RunnableKind, JobToken, FoldKind}; use ra_syntax::{ - algo::{siblings, walk, Direction}, - text_utils::contains_offset_nonstrict, - SyntaxKind, SyntaxNodeRef, TextRange + text_utils::contains_offset_nonstrict }; use ::{ @@ -375,82 +373,28 @@ pub fn handle_folding_range( _token: JobToken, ) -> Result>> { let file_id = params.text_document.try_conv_with(&world)?; - let file = world.analysis().file_syntax(file_id); let line_index = world.analysis().file_line_index(file_id); - 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(FoldingRangeKind::Comment), - ), - SyntaxKind::USE_ITEM => ( - contiguous_range_for(SyntaxKind::USE_ITEM, node, &mut visited), - Some(FoldingRangeKind::Imports), - ), - _ => (None, None), - }; - - match range_and_kind { - (Some(range), Some(kind)) => { - let range = range.conv_with(&line_index); - res.push(FoldingRange { - start_line: range.start.line, - start_character: Some(range.start.character), - end_line: range.end.line, - end_character: Some(range.start.character), - kind: Some(kind), - }); + let res = Some(world.analysis() + .folding_ranges(file_id) + .into_iter() + .map(|fold| { + let kind = match fold.kind { + FoldKind::Comment => FoldingRangeKind::Comment, + FoldKind::Imports => FoldingRangeKind::Imports + }; + let range = fold.range.conv_with(&line_index); + FoldingRange { + start_line: range.start.line, + start_character: Some(range.start.character), + end_line: range.end.line, + end_character: Some(range.start.character), + kind: Some(kind) } - _ => {} - } - } + }) + .collect()); - if res.is_empty() { - Ok(None) - } else { - Ok(Some(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 - } + Ok(res) } pub fn handle_code_action(