Provide regions in file structure

This commit is contained in:
ivan770 2021-03-11 18:14:41 +02:00
parent af8440b848
commit 71a97a2d8c
No known key found for this signature in database
GPG key ID: D8C4BD5AE4D9CC4D
5 changed files with 55 additions and 4 deletions

View file

@ -1,7 +1,8 @@
use ide_db::SymbolKind; use ide_db::SymbolKind;
use syntax::{ use syntax::{
ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent, match_ast, AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, TextRange,
WalkEvent,
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -32,20 +33,32 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
let mut res = Vec::new(); let mut res = Vec::new();
let mut stack = Vec::new(); let mut stack = Vec::new();
for event in file.syntax().preorder() { for event in file.syntax().preorder_with_tokens() {
match event { match event {
WalkEvent::Enter(node) => { WalkEvent::Enter(NodeOrToken::Node(node)) => {
if let Some(mut symbol) = structure_node(&node) { if let Some(mut symbol) = structure_node(&node) {
symbol.parent = stack.last().copied(); symbol.parent = stack.last().copied();
stack.push(res.len()); stack.push(res.len());
res.push(symbol); res.push(symbol);
} }
} }
WalkEvent::Leave(node) => { WalkEvent::Leave(NodeOrToken::Node(node)) => {
if structure_node(&node).is_some() { if structure_node(&node).is_some() {
stack.pop().unwrap(); stack.pop().unwrap();
} }
} }
WalkEvent::Enter(NodeOrToken::Token(token)) => {
if let Some(mut symbol) = structure_token(token) {
symbol.parent = stack.last().copied();
stack.push(res.len());
res.push(symbol);
}
}
WalkEvent::Leave(NodeOrToken::Token(token)) => {
if structure_token(token).is_some() {
stack.pop().unwrap();
}
}
} }
} }
res res
@ -159,6 +172,26 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
} }
} }
fn structure_token(token: SyntaxToken) -> Option<StructureNode> {
if let Some(comment) = ast::Comment::cast(token) {
let text = comment.text().trim();
if let Some(region_name) = text.strip_prefix("// region:").map(|text| text.trim()) {
return Some(StructureNode {
parent: None,
label: region_name.to_string(),
navigation_range: comment.syntax().text_range(),
node_range: comment.syntax().text_range(),
kind: SymbolKind::Region,
detail: None,
deprecated: false,
});
}
}
None
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use expect_test::{expect, Expect}; use expect_test::{expect, Expect};
@ -217,6 +250,9 @@ fn obsolete() {}
#[deprecated(note = "for awhile")] #[deprecated(note = "for awhile")]
fn very_obsolete() {} fn very_obsolete() {}
// region: Some region name
// endregion
"#, "#,
expect![[r#" expect![[r#"
[ [
@ -421,6 +457,15 @@ fn very_obsolete() {}
), ),
deprecated: true, deprecated: true,
}, },
StructureNode {
parent: None,
label: "Some region name",
navigation_range: 501..528,
node_range: 501..528,
kind: Region,
detail: None,
deprecated: false,
},
] ]
"#]], "#]],
); );

View file

@ -107,6 +107,7 @@ impl HlTag {
SymbolKind::ValueParam => "value_param", SymbolKind::ValueParam => "value_param",
SymbolKind::SelfParam => "self_keyword", SymbolKind::SelfParam => "self_keyword",
SymbolKind::Impl => "self_type", SymbolKind::Impl => "self_type",
SymbolKind::Region => "region",
}, },
HlTag::Attribute => "attribute", HlTag::Attribute => "attribute",
HlTag::BoolLiteral => "bool_literal", HlTag::BoolLiteral => "bool_literal",

View file

@ -225,6 +225,7 @@ impl CompletionItemKind {
SymbolKind::Local => "lc", SymbolKind::Local => "lc",
SymbolKind::Macro => "ma", SymbolKind::Macro => "ma",
SymbolKind::Module => "md", SymbolKind::Module => "md",
SymbolKind::Region => "rn",
SymbolKind::SelfParam => "sp", SymbolKind::SelfParam => "sp",
SymbolKind::Static => "sc", SymbolKind::Static => "sc",
SymbolKind::Struct => "st", SymbolKind::Struct => "st",

View file

@ -148,6 +148,7 @@ pub enum SymbolKind {
Local, Local,
Macro, Macro,
Module, Module,
Region,
SelfParam, SelfParam,
Static, Static,
Struct, Struct,

View file

@ -60,6 +60,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
| SymbolKind::ValueParam | SymbolKind::ValueParam
| SymbolKind::Label => lsp_types::SymbolKind::Variable, | SymbolKind::Label => lsp_types::SymbolKind::Variable,
SymbolKind::Union => lsp_types::SymbolKind::Struct, SymbolKind::Union => lsp_types::SymbolKind::Struct,
SymbolKind::Region => lsp_types::SymbolKind::Namespace,
} }
} }
@ -117,6 +118,7 @@ pub(crate) fn completion_item_kind(
SymbolKind::Local => lsp_types::CompletionItemKind::Variable, SymbolKind::Local => lsp_types::CompletionItemKind::Variable,
SymbolKind::Macro => lsp_types::CompletionItemKind::Method, SymbolKind::Macro => lsp_types::CompletionItemKind::Method,
SymbolKind::Module => lsp_types::CompletionItemKind::Module, SymbolKind::Module => lsp_types::CompletionItemKind::Module,
SymbolKind::Region => lsp_types::CompletionItemKind::Keyword,
SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value, SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value,
SymbolKind::Static => lsp_types::CompletionItemKind::Value, SymbolKind::Static => lsp_types::CompletionItemKind::Value,
SymbolKind::Struct => lsp_types::CompletionItemKind::Struct, SymbolKind::Struct => lsp_types::CompletionItemKind::Struct,
@ -428,6 +430,7 @@ fn semantic_token_type_and_modifiers(
SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS, SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS,
SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE, SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE,
SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO, SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO,
SymbolKind::Region => lsp_types::SemanticTokenType::NAMESPACE,
}, },
HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE, HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
HlTag::None => semantic_tokens::GENERIC, HlTag::None => semantic_tokens::GENERIC,