diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs index 26793bdb441..713c7695727 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 collapse_ws(node: &SyntaxNode, output: &mut String) { } } +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 3c02fdb1151..c7e74aed862 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -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", diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index 9a4b5217a01..7b553ea7ad3 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs @@ -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", diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs index 88ee4a87d51..d478841e246 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 d415ed4d39d..e88818eb04e 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,