added region folding

This commit is contained in:
Luciano Bestia 2021-01-18 19:45:42 +01:00
parent a1c72451bb
commit 9f1d341ee9
4 changed files with 92 additions and 13 deletions

23
Cargo.lock generated
View 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"

View 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" }

View file

@ -6,9 +6,11 @@ use syntax::{
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 @@ mod tests {
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();
}
}

View 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);