aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/file_structure.rs53
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs1
2 files changed, 50 insertions, 4 deletions
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 @@
1use ide_db::SymbolKind; 1use ide_db::SymbolKind;
2use syntax::{ 2use syntax::{
3 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, 3 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
4 match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent, 4 match_ast, AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, TextRange,
5 WalkEvent,
5}; 6};
6 7
7#[derive(Debug, Clone)] 8#[derive(Debug, Clone)]
@@ -32,20 +33,32 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
32 let mut res = Vec::new(); 33 let mut res = Vec::new();
33 let mut stack = Vec::new(); 34 let mut stack = Vec::new();
34 35
35 for event in file.syntax().preorder() { 36 for event in file.syntax().preorder_with_tokens() {
36 match event { 37 match event {
37 WalkEvent::Enter(node) => { 38 WalkEvent::Enter(NodeOrToken::Node(node)) => {
38 if let Some(mut symbol) = structure_node(&node) { 39 if let Some(mut symbol) = structure_node(&node) {
39 symbol.parent = stack.last().copied(); 40 symbol.parent = stack.last().copied();
40 stack.push(res.len()); 41 stack.push(res.len());
41 res.push(symbol); 42 res.push(symbol);
42 } 43 }
43 } 44 }
44 WalkEvent::Leave(node) => { 45 WalkEvent::Leave(NodeOrToken::Node(node)) => {
45 if structure_node(&node).is_some() { 46 if structure_node(&node).is_some() {
46 stack.pop().unwrap(); 47 stack.pop().unwrap();
47 } 48 }
48 } 49 }
50 WalkEvent::Enter(NodeOrToken::Token(token)) => {
51 if let Some(mut symbol) = structure_token(token) {
52 symbol.parent = stack.last().copied();
53 stack.push(res.len());
54 res.push(symbol);
55 }
56 }
57 WalkEvent::Leave(NodeOrToken::Token(token)) => {
58 if structure_token(token).is_some() {
59 stack.pop().unwrap();
60 }
61 }
49 } 62 }
50 } 63 }
51 res 64 res
@@ -159,6 +172,26 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
159 } 172 }
160} 173}
161 174
175fn structure_token(token: SyntaxToken) -> Option<StructureNode> {
176 if let Some(comment) = ast::Comment::cast(token) {
177 let text = comment.text().trim();
178
179 if let Some(region_name) = text.strip_prefix("// region:").map(|text| text.trim()) {
180 return Some(StructureNode {
181 parent: None,
182 label: region_name.to_string(),
183 navigation_range: comment.syntax().text_range(),
184 node_range: comment.syntax().text_range(),
185 kind: SymbolKind::Region,
186 detail: None,
187 deprecated: false,
188 });
189 }
190 }
191
192 None
193}
194
162#[cfg(test)] 195#[cfg(test)]
163mod tests { 196mod tests {
164 use expect_test::{expect, Expect}; 197 use expect_test::{expect, Expect};
@@ -217,6 +250,9 @@ fn obsolete() {}
217 250
218#[deprecated(note = "for awhile")] 251#[deprecated(note = "for awhile")]
219fn very_obsolete() {} 252fn very_obsolete() {}
253
254// region: Some region name
255// endregion
220"#, 256"#,
221 expect![[r#" 257 expect![[r#"
222 [ 258 [
@@ -421,6 +457,15 @@ fn very_obsolete() {}
421 ), 457 ),
422 deprecated: true, 458 deprecated: true,
423 }, 459 },
460 StructureNode {
461 parent: None,
462 label: "Some region name",
463 navigation_range: 501..528,
464 node_range: 501..528,
465 kind: Region,
466 detail: None,
467 deprecated: false,
468 },
424 ] 469 ]
425 "#]], 470 "#]],
426 ); 471 );
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 {
107 SymbolKind::ValueParam => "value_param", 107 SymbolKind::ValueParam => "value_param",
108 SymbolKind::SelfParam => "self_keyword", 108 SymbolKind::SelfParam => "self_keyword",
109 SymbolKind::Impl => "self_type", 109 SymbolKind::Impl => "self_type",
110 SymbolKind::Region => "region",
110 }, 111 },
111 HlTag::Attribute => "attribute", 112 HlTag::Attribute => "attribute",
112 HlTag::BoolLiteral => "bool_literal", 113 HlTag::BoolLiteral => "bool_literal",