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 syntax::{
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)]
@ -32,20 +33,32 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
let mut res = Vec::new();
let mut stack = Vec::new();
for event in file.syntax().preorder() {
for event in file.syntax().preorder_with_tokens() {
match event {
WalkEvent::Enter(node) => {
WalkEvent::Enter(NodeOrToken::Node(node)) => {
if let Some(mut symbol) = structure_node(&node) {
symbol.parent = stack.last().copied();
stack.push(res.len());
res.push(symbol);
}
}
WalkEvent::Leave(node) => {
WalkEvent::Leave(NodeOrToken::Node(node)) => {
if structure_node(&node).is_some() {
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
@ -159,6 +172,26 @@ fn collapse_ws(node: &SyntaxNode, output: &mut String) {
}
}
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)]
mod tests {
use expect_test::{expect, Expect};
@ -217,6 +250,9 @@ fn obsolete() {}
#[deprecated(note = "for awhile")]
fn very_obsolete() {}
// region: Some region name
// endregion
"#,
expect![[r#"
[
@ -421,6 +457,15 @@ fn very_obsolete() {}
),
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 @@ fn as_str(self) -> &'static str {
SymbolKind::ValueParam => "value_param",
SymbolKind::SelfParam => "self_keyword",
SymbolKind::Impl => "self_type",
SymbolKind::Region => "region",
},
HlTag::Attribute => "attribute",
HlTag::BoolLiteral => "bool_literal",

View File

@ -225,6 +225,7 @@ pub(crate) fn tag(&self) -> &'static str {
SymbolKind::Local => "lc",
SymbolKind::Macro => "ma",
SymbolKind::Module => "md",
SymbolKind::Region => "rn",
SymbolKind::SelfParam => "sp",
SymbolKind::Static => "sc",
SymbolKind::Struct => "st",

View File

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

View File

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