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 + 2 files changed, 50 insertions(+), 4 deletions(-) (limited to 'crates/ide') 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", -- cgit v1.2.3