From 27c071f7023a529d1c530e2fc3dccc1c0b65c860 Mon Sep 17 00:00:00 2001 From: Andrea Pretto Date: Fri, 25 Jan 2019 23:37:45 +0100 Subject: Fold blocks of mod items. Fixes #572 --- crates/ra_ide_api_light/src/folding_ranges.rs | 60 +++++++++++++++++++++++++- crates/ra_lsp_server/src/main_loop/handlers.rs | 1 + 2 files changed, 60 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/ra_ide_api_light/src/folding_ranges.rs b/crates/ra_ide_api_light/src/folding_ranges.rs index 288bba0ce..0f2f1399b 100644 --- a/crates/ra_ide_api_light/src/folding_ranges.rs +++ b/crates/ra_ide_api_light/src/folding_ranges.rs @@ -9,6 +9,7 @@ use ra_syntax::{ pub enum FoldKind { Comment, Imports, + Mods, Block, } @@ -22,6 +23,7 @@ pub fn folding_ranges(file: &SourceFile) -> Vec { let mut res = vec![]; let mut visited_comments = FxHashSet::default(); let mut visited_imports = FxHashSet::default(); + let mut visited_mods = FxHashSet::default(); for node in file.syntax().descendants() { // Fold items that span multiple lines @@ -53,6 +55,18 @@ pub fn folding_ranges(file: &SourceFile) -> Vec { }) } } + + // Fold groups of mods + if node.kind() == MODULE && !has_visibility(&node) && !visited_mods.contains(&node) { + if let Some(range) = + contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods) + { + res.push(Fold { + range, + kind: FoldKind::Mods, + }) + } + } } res @@ -68,6 +82,10 @@ fn fold_kind(kind: SyntaxKind) -> Option { } } +fn has_visibility(node: &SyntaxNode) -> bool { + return node.descendants().any(|n| n.kind() == VISIBILITY); +} + fn has_newline(node: &SyntaxNode) -> bool { for descendant in node.descendants() { if let Some(ws) = ast::Whitespace::cast(descendant) { @@ -87,6 +105,14 @@ fn has_newline(node: &SyntaxNode) -> bool { fn contiguous_range_for_group<'a>( first: &'a SyntaxNode, visited: &mut FxHashSet<&'a SyntaxNode>, +) -> Option { + contiguous_range_for_group_unless(first, |_| false, visited) +} + +fn contiguous_range_for_group_unless<'a>( + first: &'a SyntaxNode, + unless: impl Fn(&'a SyntaxNode) -> bool, + visited: &mut FxHashSet<&'a SyntaxNode>, ) -> Option { visited.insert(first); @@ -103,7 +129,7 @@ fn contiguous_range_for_group<'a>( } // Stop if we find a node that doesn't belong to the group - if node.kind() != first.kind() { + if node.kind() != first.kind() || unless(node) { break; } @@ -244,6 +270,38 @@ fn main() { do_check(text, folds); } + #[test] + fn test_fold_mods() { + let text = r#" + +pub mod foo; +mod after_pub; +mod after_pub_next; + +mod before_pub; +mod before_pub_next; +pub mod bar; + +mod not_folding_single; +pub mod foobar; +pub not_folding_single_next; + +#[cfg(test)] +mod with_attribute; +mod with_attribute_next; + +fn main() { +}"#; + + let folds = &[ + FoldKind::Mods, + FoldKind::Mods, + FoldKind::Mods, + FoldKind::Block, + ]; + do_check(text, folds); + } + #[test] fn test_fold_import_groups() { let text = r#" diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index c0fe0216d..8ea9edc84 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -369,6 +369,7 @@ pub fn handle_folding_range( let kind = match fold.kind { FoldKind::Comment => Some(FoldingRangeKind::Comment), FoldKind::Imports => Some(FoldingRangeKind::Imports), + FoldKind::Mods => None, FoldKind::Block => None, }; let range = fold.range.conv_with(&line_index); -- cgit v1.2.3 From b9ca8ab868a051fca47462113490433a5085d3c8 Mon Sep 17 00:00:00 2001 From: Andrea Pretto Date: Sat, 26 Jan 2019 13:21:41 +0100 Subject: Better visibility check. --- crates/ra_ide_api_light/src/folding_ranges.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/ra_ide_api_light/src/folding_ranges.rs b/crates/ra_ide_api_light/src/folding_ranges.rs index 0f2f1399b..87feb9bd8 100644 --- a/crates/ra_ide_api_light/src/folding_ranges.rs +++ b/crates/ra_ide_api_light/src/folding_ranges.rs @@ -83,7 +83,11 @@ fn fold_kind(kind: SyntaxKind) -> Option { } fn has_visibility(node: &SyntaxNode) -> bool { - return node.descendants().any(|n| n.kind() == VISIBILITY); + use ast::VisibilityOwner; + + return ast::Module::cast(node) + .and_then(|m| m.visibility()) + .is_some(); } fn has_newline(node: &SyntaxNode) -> bool { -- cgit v1.2.3