diff options
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r-- | crates/libeditor/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/libeditor/src/symbols.rs | 82 |
2 files changed, 72 insertions, 12 deletions
diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index e5933cbd6..b40db2c66 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs | |||
@@ -19,7 +19,7 @@ pub use libsyntax2::{File, TextRange, TextUnit}; | |||
19 | pub use self::{ | 19 | pub use self::{ |
20 | line_index::{LineIndex, LineCol}, | 20 | line_index::{LineIndex, LineCol}, |
21 | extend_selection::extend_selection, | 21 | extend_selection::extend_selection, |
22 | symbols::{FileSymbol, file_symbols}, | 22 | symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, |
23 | edit::{EditBuilder, Edit, AtomEdit}, | 23 | edit::{EditBuilder, Edit, AtomEdit}, |
24 | code_actions::{flip_comma}, | 24 | code_actions::{flip_comma}, |
25 | }; | 25 | }; |
diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs index f1d5222f4..43f4164da 100644 --- a/crates/libeditor/src/symbols.rs +++ b/crates/libeditor/src/symbols.rs | |||
@@ -4,22 +4,58 @@ use libsyntax2::{ | |||
4 | ast::{self, NameOwner}, | 4 | ast::{self, NameOwner}, |
5 | algo::{ | 5 | algo::{ |
6 | visit::{visitor, Visitor}, | 6 | visit::{visitor, Visitor}, |
7 | walk::{walk, WalkEvent}, | 7 | walk::{walk, WalkEvent, preorder}, |
8 | }, | 8 | }, |
9 | SyntaxKind::*, | ||
9 | }; | 10 | }; |
10 | use TextRange; | 11 | use TextRange; |
11 | 12 | ||
12 | #[derive(Debug)] | 13 | #[derive(Debug)] |
13 | pub struct FileSymbol { | 14 | pub struct StructureNode { |
14 | pub parent: Option<usize>, | 15 | pub parent: Option<usize>, |
15 | pub name: SmolStr, | 16 | pub label: String, |
16 | pub name_range: TextRange, | 17 | pub navigation_range: TextRange, |
17 | pub node_range: TextRange, | 18 | pub node_range: TextRange, |
18 | pub kind: SyntaxKind, | 19 | pub kind: SyntaxKind, |
19 | } | 20 | } |
20 | 21 | ||
22 | #[derive(Debug)] | ||
23 | pub struct FileSymbol { | ||
24 | pub name: SmolStr, | ||
25 | pub node_range: TextRange, | ||
26 | pub kind: SyntaxKind, | ||
27 | } | ||
21 | 28 | ||
22 | pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { | 29 | pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { |
30 | let syntax = file.syntax(); | ||
31 | preorder(syntax.as_ref()) | ||
32 | .filter_map(to_symbol) | ||
33 | .collect() | ||
34 | } | ||
35 | |||
36 | fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { | ||
37 | fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<FileSymbol> { | ||
38 | let name = node.name()?; | ||
39 | Some(FileSymbol { | ||
40 | name: name.text(), | ||
41 | node_range: node.syntax().range(), | ||
42 | kind: node.syntax().kind(), | ||
43 | }) | ||
44 | } | ||
45 | visitor() | ||
46 | .visit(decl::<ast::FnDef<_>>) | ||
47 | .visit(decl::<ast::StructDef<_>>) | ||
48 | .visit(decl::<ast::EnumDef<_>>) | ||
49 | .visit(decl::<ast::TraitDef<_>>) | ||
50 | .visit(decl::<ast::Module<_>>) | ||
51 | .visit(decl::<ast::TypeDef<_>>) | ||
52 | .visit(decl::<ast::ConstDef<_>>) | ||
53 | .visit(decl::<ast::StaticDef<_>>) | ||
54 | .accept(node)? | ||
55 | } | ||
56 | |||
57 | |||
58 | pub fn file_structure(file: &ast::File) -> Vec<StructureNode> { | ||
23 | let mut res = Vec::new(); | 59 | let mut res = Vec::new(); |
24 | let mut stack = Vec::new(); | 60 | let mut stack = Vec::new(); |
25 | let syntax = file.syntax(); | 61 | let syntax = file.syntax(); |
@@ -27,7 +63,7 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { | |||
27 | for event in walk(syntax.as_ref()) { | 63 | for event in walk(syntax.as_ref()) { |
28 | match event { | 64 | match event { |
29 | WalkEvent::Enter(node) => { | 65 | WalkEvent::Enter(node) => { |
30 | match to_symbol(node) { | 66 | match structure_node(node) { |
31 | Some(mut symbol) => { | 67 | Some(mut symbol) => { |
32 | symbol.parent = stack.last().map(|&n| n); | 68 | symbol.parent = stack.last().map(|&n| n); |
33 | stack.push(res.len()); | 69 | stack.push(res.len()); |
@@ -37,7 +73,7 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { | |||
37 | } | 73 | } |
38 | } | 74 | } |
39 | WalkEvent::Exit(node) => { | 75 | WalkEvent::Exit(node) => { |
40 | if to_symbol(node).is_some() { | 76 | if structure_node(node).is_some() { |
41 | stack.pop().unwrap(); | 77 | stack.pop().unwrap(); |
42 | } | 78 | } |
43 | } | 79 | } |
@@ -46,13 +82,13 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { | |||
46 | res | 82 | res |
47 | } | 83 | } |
48 | 84 | ||
49 | fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { | 85 | fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> { |
50 | fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<FileSymbol> { | 86 | fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<StructureNode> { |
51 | let name = node.name()?; | 87 | let name = node.name()?; |
52 | Some(FileSymbol { | 88 | Some(StructureNode { |
53 | parent: None, | 89 | parent: None, |
54 | name: name.text(), | 90 | label: name.text().to_string(), |
55 | name_range: name.syntax().range(), | 91 | navigation_range: name.syntax().range(), |
56 | node_range: node.syntax().range(), | 92 | node_range: node.syntax().range(), |
57 | kind: node.syntax().kind(), | 93 | kind: node.syntax().kind(), |
58 | }) | 94 | }) |
@@ -67,5 +103,29 @@ fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { | |||
67 | .visit(decl::<ast::TypeDef<_>>) | 103 | .visit(decl::<ast::TypeDef<_>>) |
68 | .visit(decl::<ast::ConstDef<_>>) | 104 | .visit(decl::<ast::ConstDef<_>>) |
69 | .visit(decl::<ast::StaticDef<_>>) | 105 | .visit(decl::<ast::StaticDef<_>>) |
106 | .visit(|im: ast::ImplItem<_>| { | ||
107 | let mut label = String::new(); | ||
108 | let brace = im.syntax().children() | ||
109 | .find(|it| { | ||
110 | let stop = it.kind() == L_CURLY; | ||
111 | if !stop { | ||
112 | label.push_str(&it.text()); | ||
113 | } | ||
114 | stop | ||
115 | })?; | ||
116 | let navigation_range = TextRange::from_to( | ||
117 | im.syntax().range().start(), | ||
118 | brace.range().start(), | ||
119 | ); | ||
120 | |||
121 | let node = StructureNode { | ||
122 | parent: None, | ||
123 | label, | ||
124 | navigation_range, | ||
125 | node_range: im.syntax().range(), | ||
126 | kind: im.syntax().kind(), | ||
127 | }; | ||
128 | Some(node) | ||
129 | }) | ||
70 | .accept(node)? | 130 | .accept(node)? |
71 | } | 131 | } |