mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
Merge #659
659: Fold blocks of mod items r=matklad a=eulerdisk Fixes #572 As requested, we ignore `mod`s with a visibility specifier. Co-authored-by: Andrea Pretto <eulerdisk@gmail.com>
This commit is contained in:
commit
3feaf2a008
2 changed files with 64 additions and 1 deletions
|
@ -9,6 +9,7 @@ use ra_syntax::{
|
||||||
pub enum FoldKind {
|
pub enum FoldKind {
|
||||||
Comment,
|
Comment,
|
||||||
Imports,
|
Imports,
|
||||||
|
Mods,
|
||||||
Block,
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
let mut visited_comments = FxHashSet::default();
|
let mut visited_comments = FxHashSet::default();
|
||||||
let mut visited_imports = FxHashSet::default();
|
let mut visited_imports = FxHashSet::default();
|
||||||
|
let mut visited_mods = FxHashSet::default();
|
||||||
|
|
||||||
for node in file.syntax().descendants() {
|
for node in file.syntax().descendants() {
|
||||||
// Fold items that span multiple lines
|
// Fold items that span multiple lines
|
||||||
|
@ -53,6 +55,18 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fold groups of mods
|
||||||
|
if node.kind() == MODULE && !has_visibility(&node) && !visited_mods.contains(&node) {
|
||||||
|
if let Some(range) =
|
||||||
|
contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods)
|
||||||
|
{
|
||||||
|
res.push(Fold {
|
||||||
|
range,
|
||||||
|
kind: FoldKind::Mods,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -68,6 +82,14 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_visibility(node: &SyntaxNode) -> bool {
|
||||||
|
use ast::VisibilityOwner;
|
||||||
|
|
||||||
|
return ast::Module::cast(node)
|
||||||
|
.and_then(|m| m.visibility())
|
||||||
|
.is_some();
|
||||||
|
}
|
||||||
|
|
||||||
fn has_newline(node: &SyntaxNode) -> bool {
|
fn has_newline(node: &SyntaxNode) -> bool {
|
||||||
for descendant in node.descendants() {
|
for descendant in node.descendants() {
|
||||||
if let Some(ws) = ast::Whitespace::cast(descendant) {
|
if let Some(ws) = ast::Whitespace::cast(descendant) {
|
||||||
|
@ -87,6 +109,14 @@ fn has_newline(node: &SyntaxNode) -> bool {
|
||||||
fn contiguous_range_for_group<'a>(
|
fn contiguous_range_for_group<'a>(
|
||||||
first: &'a SyntaxNode,
|
first: &'a SyntaxNode,
|
||||||
visited: &mut FxHashSet<&'a SyntaxNode>,
|
visited: &mut FxHashSet<&'a SyntaxNode>,
|
||||||
|
) -> Option<TextRange> {
|
||||||
|
contiguous_range_for_group_unless(first, |_| false, visited)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contiguous_range_for_group_unless<'a>(
|
||||||
|
first: &'a SyntaxNode,
|
||||||
|
unless: impl Fn(&'a SyntaxNode) -> bool,
|
||||||
|
visited: &mut FxHashSet<&'a SyntaxNode>,
|
||||||
) -> Option<TextRange> {
|
) -> Option<TextRange> {
|
||||||
visited.insert(first);
|
visited.insert(first);
|
||||||
|
|
||||||
|
@ -103,7 +133,7 @@ fn contiguous_range_for_group<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop if we find a node that doesn't belong to the group
|
// Stop if we find a node that doesn't belong to the group
|
||||||
if node.kind() != first.kind() {
|
if node.kind() != first.kind() || unless(node) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +274,38 @@ fn main() <fold>{
|
||||||
do_check(text, folds);
|
do_check(text, folds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_mods() {
|
||||||
|
let text = r#"
|
||||||
|
|
||||||
|
pub mod foo;
|
||||||
|
<fold>mod after_pub;
|
||||||
|
mod after_pub_next;</fold>
|
||||||
|
|
||||||
|
<fold>mod before_pub;
|
||||||
|
mod before_pub_next;</fold>
|
||||||
|
pub mod bar;
|
||||||
|
|
||||||
|
mod not_folding_single;
|
||||||
|
pub mod foobar;
|
||||||
|
pub not_folding_single_next;
|
||||||
|
|
||||||
|
<fold>#[cfg(test)]
|
||||||
|
mod with_attribute;
|
||||||
|
mod with_attribute_next;</fold>
|
||||||
|
|
||||||
|
fn main() <fold>{
|
||||||
|
}</fold>"#;
|
||||||
|
|
||||||
|
let folds = &[
|
||||||
|
FoldKind::Mods,
|
||||||
|
FoldKind::Mods,
|
||||||
|
FoldKind::Mods,
|
||||||
|
FoldKind::Block,
|
||||||
|
];
|
||||||
|
do_check(text, folds);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fold_import_groups() {
|
fn test_fold_import_groups() {
|
||||||
let text = r#"
|
let text = r#"
|
||||||
|
|
|
@ -369,6 +369,7 @@ pub fn handle_folding_range(
|
||||||
let kind = match fold.kind {
|
let kind = match fold.kind {
|
||||||
FoldKind::Comment => Some(FoldingRangeKind::Comment),
|
FoldKind::Comment => Some(FoldingRangeKind::Comment),
|
||||||
FoldKind::Imports => Some(FoldingRangeKind::Imports),
|
FoldKind::Imports => Some(FoldingRangeKind::Imports),
|
||||||
|
FoldKind::Mods => None,
|
||||||
FoldKind::Block => None,
|
FoldKind::Block => None,
|
||||||
};
|
};
|
||||||
let range = fold.range.conv_with(&line_index);
|
let range = fold.range.conv_with(&line_index);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue