From 71a97a2d8c30fc4061a545f1e2db10e3559eae36 Mon Sep 17 00:00:00 2001 From: ivan770 Date: Thu, 11 Mar 2021 18:14:41 +0200 Subject: Provide regions in file structure --- crates/ide/src/file_structure.rs | 53 +++++++++++++++++++++++++++--- crates/ide/src/syntax_highlighting/tags.rs | 1 + crates/ide_completion/src/item.rs | 1 + crates/ide_db/src/lib.rs | 1 + crates/rust-analyzer/src/to_proto.rs | 3 ++ 5 files changed, 55 insertions(+), 4 deletions(-) (limited to 'crates') diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs index 26793bdb4..713c76957 100644 --- a/crates/ide/src/file_structure.rs +++ b/crates/ide/src/file_structure.rs @@ -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 { 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 structure_node(node: &SyntaxNode) -> Option { } } +fn structure_token(token: SyntaxToken) -> Option { + 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, + }, ] "#]], ); diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 3c02fdb11..c7e74aed8 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -107,6 +107,7 @@ impl HlTag { SymbolKind::ValueParam => "value_param", SymbolKind::SelfParam => "self_keyword", SymbolKind::Impl => "self_type", + SymbolKind::Region => "region", }, HlTag::Attribute => "attribute", HlTag::BoolLiteral => "bool_literal", diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index 9a4b5217a..7b553ea7a 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs @@ -225,6 +225,7 @@ impl CompletionItemKind { SymbolKind::Local => "lc", SymbolKind::Macro => "ma", SymbolKind::Module => "md", + SymbolKind::Region => "rn", SymbolKind::SelfParam => "sp", SymbolKind::Static => "sc", SymbolKind::Struct => "st", diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs index 88ee4a87d..d478841e2 100644 --- a/crates/ide_db/src/lib.rs +++ b/crates/ide_db/src/lib.rs @@ -148,6 +148,7 @@ pub enum SymbolKind { Local, Macro, Module, + Region, SelfParam, Static, Struct, diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index d415ed4d3..e88818eb0 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -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, -- cgit v1.2.3