]> git.lizzy.rs Git - rust.git/commitdiff
added region folding
authorLuciano Bestia <LucianoBestia@gmail.com>
Mon, 18 Jan 2021 18:45:42 +0000 (19:45 +0100)
committerLuciano Bestia <LucianoBestia@gmail.com>
Mon, 18 Jan 2021 18:45:42 +0000 (19:45 +0100)
Cargo.lock
crates/ide/Cargo.toml
crates/ide/src/folding_ranges.rs
crates/rust-analyzer/src/to_proto.rs

index aac473191fe43b03dfeb25f8b559d8097547de7b..674c75450b8d21108b194cdcfc02bd1872434814 100644 (file)
@@ -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"
index bb28cca4d41414ff820fc80b09232711990976ee..6ec1064267e308eab020dc90e0fc992cb7eeb3d2 100644 (file)
@@ -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" }
index 45170dd29de0507238406caadec7062eba50e466..99f0c3c99af7397c691a75370a4f9312741ff9c0 100644 (file)
@@ -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<Fold> {
     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<TextSize> = 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> {
                 // 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<fold arglist>(
 "#,
         )
     }
+
+    #[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
+<fold region>// region: test
+// 2. some normal comment
+calling_function(x,y);
+// endregion: test</fold>
+"#,
+        )
+    }
+
+    fn log_init_for_test_debug() {
+        let _ = env_logger::builder().is_test(true).try_init();
+    }
 }
index 1ff2d3fea659a76ca95a289c0a7981d3a1a42b3d..c903ab523ca1b22189ab48b3183a39eda1986123 100644 (file)
@@ -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);