added region folding
This commit is contained in:
parent
a1c72451bb
commit
9f1d341ee9
4 changed files with 92 additions and 13 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue