diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/file_structure.rs | 53 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/tags.rs | 1 |
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 @@ | |||
1 | use ide_db::SymbolKind; | 1 | use ide_db::SymbolKind; |
2 | use syntax::{ | 2 | use 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 | ||
175 | fn 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)] |
163 | mod tests { | 196 | mod 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")] |
219 | fn very_obsolete() {} | 252 | fn 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", |