Skip to content

Commit 9f1d341

Browse files
Luciano BestiaLuciano Bestia
authored andcommitted
added region folding
1 parent a1c7245 commit 9f1d341

File tree

4 files changed

+92
-13
lines changed

4 files changed

+92
-13
lines changed

Cargo.lock

Lines changed: 19 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ide/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ assists = { path = "../assists", version = "0.0.0" }
3131
ssr = { path = "../ssr", version = "0.0.0" }
3232
completion = { path = "../completion", version = "0.0.0" }
3333

34+
lazy_static = "1.4.0"
35+
regex = "1.4.3"
36+
env_logger = { version = "0.8.1", default-features = false }
37+
3438
# ide should depend only on the top-level `hir` package. if you need
3539
# something from some `hir_xxx` subpackage, reexport the API via `hir`.
3640
hir = { path = "../hir", version = "0.0.0" }

crates/ide/src/folding_ranges.rs

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ use syntax::{
66
ast::{self, AstNode, AstToken, VisibilityOwner},
77
Direction, NodeOrToken, SourceFile,
88
SyntaxKind::{self, *},
9-
SyntaxNode, TextRange,
9+
SyntaxNode, TextRange, TextSize,
1010
};
1111

12+
use lazy_static::lazy_static;
13+
1214
#[derive(Debug, PartialEq, Eq)]
1315
pub enum FoldKind {
1416
Comment,
1517
Imports,
1618
Mods,
1719
Block,
1820
ArgList,
21+
Region,
1922
}
2023

2124
#[derive(Debug)]
@@ -29,6 +32,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
2932
let mut visited_comments = FxHashSet::default();
3033
let mut visited_imports = FxHashSet::default();
3134
let mut visited_mods = FxHashSet::default();
35+
// regions can be nested, here is a LIFO buffer
36+
let mut regions_starts: Vec<TextSize> = vec![];
3237

3338
for element in file.syntax().descendants_with_tokens() {
3439
// Fold items that span multiple lines
@@ -48,10 +53,32 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
4853
// Fold groups of comments
4954
if let Some(comment) = ast::Comment::cast(token) {
5055
if !visited_comments.contains(&comment) {
51-
if let Some(range) =
52-
contiguous_range_for_comment(comment, &mut visited_comments)
53-
{
54-
res.push(Fold { range, kind: FoldKind::Comment })
56+
// regions are not really comments
57+
use regex::Regex;
58+
lazy_static! {
59+
static ref RE_START: Regex =
60+
Regex::new(r"^\s*//\s*#?region\b").unwrap();
61+
static ref RE_END: Regex =
62+
Regex::new(r"^\s*//\s*#?endregion\b").unwrap();
63+
}
64+
if RE_START.is_match(comment.text()) {
65+
regions_starts.push(comment.syntax().text_range().start());
66+
} else if RE_END.is_match(comment.text()) {
67+
if !regions_starts.is_empty() {
68+
res.push(Fold {
69+
range: TextRange::new(
70+
regions_starts.pop().unwrap(),
71+
comment.syntax().text_range().end(),
72+
),
73+
kind: FoldKind::Region,
74+
})
75+
}
76+
} else {
77+
if let Some(range) =
78+
contiguous_range_for_comment(comment, &mut visited_comments)
79+
{
80+
res.push(Fold { range, kind: FoldKind::Comment })
81+
}
5582
}
5683
}
5784
}
@@ -175,9 +202,21 @@ fn contiguous_range_for_comment(
175202
}
176203
if let Some(c) = ast::Comment::cast(token) {
177204
if c.kind() == group_kind {
178-
visited.insert(c.clone());
179-
last = c;
180-
continue;
205+
// regions are not really comments
206+
use regex::Regex;
207+
lazy_static! {
208+
static ref RE_START: Regex =
209+
Regex::new(r"^\s*//\s*#?region\b").unwrap();
210+
static ref RE_END: Regex =
211+
Regex::new(r"^\s*//\s*#?endregion\b").unwrap();
212+
}
213+
if RE_START.is_match(c.text()) || RE_END.is_match(c.text()) {
214+
break;
215+
} else {
216+
visited.insert(c.clone());
217+
last = c;
218+
continue;
219+
}
181220
}
182221
}
183222
// The comment group ends because either:
@@ -224,6 +263,7 @@ mod tests {
224263
FoldKind::Mods => "mods",
225264
FoldKind::Block => "block",
226265
FoldKind::ArgList => "arglist",
266+
FoldKind::Region => "region",
227267
};
228268
assert_eq!(kind, &attr.unwrap());
229269
}
@@ -418,4 +458,24 @@ fn foo<fold arglist>(
418458
"#,
419459
)
420460
}
461+
462+
#[test]
463+
fn fold_region() {
464+
log_init_for_test_debug();
465+
// only error level log is printed on the terminal
466+
log::error!("test fold_region");
467+
check(
468+
r#"
469+
// 1. some normal comment
470+
<fold region>// region: test
471+
// 2. some normal comment
472+
calling_function(x,y);
473+
// endregion: test</fold>
474+
"#,
475+
)
476+
}
477+
478+
fn log_init_for_test_debug() {
479+
let _ = env_logger::builder().is_test(true).try_init();
480+
}
421481
}

crates/rust-analyzer/src/to_proto.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ pub(crate) fn folding_range(
465465
let kind = match fold.kind {
466466
FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
467467
FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
468-
FoldKind::Mods | FoldKind::Block | FoldKind::ArgList => None,
468+
FoldKind::Mods | FoldKind::Block | FoldKind::ArgList | FoldKind::Region => None,
469469
};
470470

471471
let range = range(line_index, fold.range);

0 commit comments

Comments
 (0)