mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-31 07:37:30 +00:00
7335: added region folding r=matklad a=LucianoBestia Regions of code that you'd like to be folded can be wrapped with `// #region` and `// #endregion` line comments. This is called "Region Folding". It is originally available for many languages in VSCode. But Rust-analyzer has its own folding function and this is missing. With this Pull Request I am suggesting a simple solution. The regions are a special kind of comments, so I added a bit of code in the comment folding function. The regex to match are: `^\s*//\s*#?region\b` and `^\s*//\s*#?endregion\b`. The number of space characters is not important. There is an optional # character. The line can end with a name of the region. Example: ```rust // 1. some normal comment // region: test // 2. some normal comment calling_function(x,y); // endregion: test ``` I added a test for this new functionality in `folding_ranges.rs`. Please, take a look and comment. I found that these exact regexes are already present in the file `language-configuration.json`, but I don't find a way to read this configuration. So my regex is hardcoded in the code. 7691: Suggest name in extract variable r=matklad a=cpud36 Generate better default name in extract variable assist as was mentioned in issue #1587 # Currently supported (in order of declining precedence) 1. Expr is argument to a function; use corresponding parameter name 2. Expr is result of a function or method call; use this function/method's name 3. Use expr type name (if possible) 4. Fallback to `var_name` otherwise # Showcase   # Questions * Should we more aggressively strip known types? E.g. we already strip `&T -> T`; should we strip `Option<T> -> T`, `Result<T, E> -> T`, and others? * Integers and floats use `var_name` by default. Should we introduce a name, like `i`, `f` etc? * Can we return a list and suggest a name when renaming(like IntelliJ does)? * Should we add counters to remove duplicate variables? E.g. `type`, `type1`, type2`, etc. Co-authored-by: Luciano Bestia <LucianoBestia@gmail.com> Co-authored-by: Luciano <31509965+LucianoBestia@users.noreply.github.com> Co-authored-by: Vladyslav Katasonov <cpud47@gmail.com>
This commit is contained in:
commit
657ec3616f
6 changed files with 1174 additions and 16 deletions
|
@ -6,7 +6,7 @@ use syntax::{
|
|||
ast::{self, AstNode, AstToken, VisibilityOwner},
|
||||
Direction, NodeOrToken, SourceFile,
|
||||
SyntaxKind::{self, *},
|
||||
SyntaxNode, TextRange,
|
||||
SyntaxNode, TextRange, TextSize,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
@ -16,6 +16,7 @@ pub enum FoldKind {
|
|||
Mods,
|
||||
Block,
|
||||
ArgList,
|
||||
Region,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -29,6 +30,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 +51,25 @@ 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 real comments
|
||||
if comment.text().trim().starts_with("// region:") {
|
||||
regions_starts.push(comment.syntax().text_range().start());
|
||||
} else if comment.text().trim().starts_with("// endregion") {
|
||||
if let Some(region) = regions_starts.pop() {
|
||||
res.push(Fold {
|
||||
range: TextRange::new(
|
||||
region,
|
||||
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 +193,16 @@ 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 real comments
|
||||
if c.text().trim().starts_with("// region:")
|
||||
|| c.text().trim().starts_with("// endregion")
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
visited.insert(c.clone());
|
||||
last = c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The comment group ends because either:
|
||||
|
@ -224,6 +249,7 @@ mod tests {
|
|||
FoldKind::Mods => "mods",
|
||||
FoldKind::Block => "block",
|
||||
FoldKind::ArgList => "arglist",
|
||||
FoldKind::Region => "region",
|
||||
};
|
||||
assert_eq!(kind, &attr.unwrap());
|
||||
}
|
||||
|
@ -415,6 +441,19 @@ fn foo<fold arglist>(
|
|||
x: i32,
|
||||
y: String,
|
||||
)</fold> {}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fold_region() {
|
||||
check(
|
||||
r#"
|
||||
// 1. some normal comment
|
||||
<fold region>// region: test
|
||||
// 2. some normal comment
|
||||
calling_function(x,y);
|
||||
// endregion: test</fold>
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue