Provide regions in file structure
This commit is contained in:
parent
af8440b848
commit
71a97a2d8c
@ -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,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -148,6 +148,7 @@ pub enum SymbolKind {
|
||||
Local,
|
||||
Macro,
|
||||
Module,
|
||||
Region,
|
||||
SelfParam,
|
||||
Static,
|
||||
Struct,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user