From: Luciano Bestia Date: Mon, 18 Jan 2021 18:45:42 +0000 (+0100) Subject: added region folding X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=9f1d341ee9bf399fa8fa2a5d2fb5f91e1b319702;p=rust.git added region folding --- diff --git a/Cargo.lock b/Cargo.lock index aac473191fe..674c75450b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -634,16 +643,19 @@ dependencies = [ "cfg", "completion", "either", + "env_logger", "expect-test", "hir", "ide_db", "indexmap", "itertools 0.10.0", + "lazy_static", "log", "oorandom", "profile", "pulldown-cmark", "pulldown-cmark-to-cmark", + "regex", "rustc-hash", "ssr", "stdx", @@ -1301,11 +1313,14 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "regex" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", + "thread_local", ] [[package]] @@ -1320,9 +1335,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "rowan" diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index bb28cca4d41..6ec1064267e 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml @@ -31,6 +31,10 @@ assists = { path = "../assists", version = "0.0.0" } ssr = { path = "../ssr", version = "0.0.0" } completion = { path = "../completion", version = "0.0.0" } +lazy_static = "1.4.0" +regex = "1.4.3" +env_logger = { version = "0.8.1", default-features = false } + # ide should depend only on the top-level `hir` package. if you need # something from some `hir_xxx` subpackage, reexport the API via `hir`. hir = { path = "../hir", version = "0.0.0" } diff --git a/crates/ide/src/folding_ranges.rs b/crates/ide/src/folding_ranges.rs index 45170dd29de..99f0c3c99af 100644 --- a/crates/ide/src/folding_ranges.rs +++ b/crates/ide/src/folding_ranges.rs @@ -6,9 +6,11 @@ ast::{self, AstNode, AstToken, VisibilityOwner}, Direction, NodeOrToken, SourceFile, SyntaxKind::{self, *}, - SyntaxNode, TextRange, + SyntaxNode, TextRange, TextSize, }; +use lazy_static::lazy_static; + #[derive(Debug, PartialEq, Eq)] pub enum FoldKind { Comment, @@ -16,6 +18,7 @@ pub enum FoldKind { Mods, Block, ArgList, + Region, } #[derive(Debug)] @@ -29,6 +32,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec { let mut visited_comments = FxHashSet::default(); let mut visited_imports = FxHashSet::default(); let mut visited_mods = FxHashSet::default(); + // regions can be nested, here is a LIFO buffer + let mut regions_starts: Vec = vec![]; for element in file.syntax().descendants_with_tokens() { // Fold items that span multiple lines @@ -48,10 +53,32 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec { // Fold groups of comments if let Some(comment) = ast::Comment::cast(token) { if !visited_comments.contains(&comment) { - if let Some(range) = - contiguous_range_for_comment(comment, &mut visited_comments) - { - res.push(Fold { range, kind: FoldKind::Comment }) + // regions are not really comments + use regex::Regex; + lazy_static! { + static ref RE_START: Regex = + Regex::new(r"^\s*//\s*#?region\b").unwrap(); + static ref RE_END: Regex = + Regex::new(r"^\s*//\s*#?endregion\b").unwrap(); + } + if RE_START.is_match(comment.text()) { + regions_starts.push(comment.syntax().text_range().start()); + } else if RE_END.is_match(comment.text()) { + if !regions_starts.is_empty() { + res.push(Fold { + range: TextRange::new( + regions_starts.pop().unwrap(), + comment.syntax().text_range().end(), + ), + kind: FoldKind::Region, + }) + } + } else { + if let Some(range) = + contiguous_range_for_comment(comment, &mut visited_comments) + { + res.push(Fold { range, kind: FoldKind::Comment }) + } } } } @@ -175,9 +202,21 @@ fn contiguous_range_for_comment( } if let Some(c) = ast::Comment::cast(token) { if c.kind() == group_kind { - visited.insert(c.clone()); - last = c; - continue; + // regions are not really comments + use regex::Regex; + lazy_static! { + static ref RE_START: Regex = + Regex::new(r"^\s*//\s*#?region\b").unwrap(); + static ref RE_END: Regex = + Regex::new(r"^\s*//\s*#?endregion\b").unwrap(); + } + if RE_START.is_match(c.text()) || RE_END.is_match(c.text()) { + break; + } else { + visited.insert(c.clone()); + last = c; + continue; + } } } // The comment group ends because either: @@ -224,6 +263,7 @@ fn check(ra_fixture: &str) { FoldKind::Mods => "mods", FoldKind::Block => "block", FoldKind::ArgList => "arglist", + FoldKind::Region => "region", }; assert_eq!(kind, &attr.unwrap()); } @@ -418,4 +458,24 @@ fn foo( "#, ) } + + #[test] + fn fold_region() { + log_init_for_test_debug(); + // only error level log is printed on the terminal + log::error!("test fold_region"); + check( + r#" +// 1. some normal comment +// region: test +// 2. some normal comment +calling_function(x,y); +// endregion: test +"#, + ) + } + + fn log_init_for_test_debug() { + let _ = env_logger::builder().is_test(true).try_init(); + } } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 1ff2d3fea65..c903ab523ca 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -465,7 +465,7 @@ pub(crate) fn folding_range( let kind = match fold.kind { FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment), FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports), - FoldKind::Mods | FoldKind::Block | FoldKind::ArgList => None, + FoldKind::Mods | FoldKind::Block | FoldKind::ArgList | FoldKind::Region => None, }; let range = range(line_index, fold.range);