diff options
Diffstat (limited to 'crates/libeditor/src/symbols.rs')
-rw-r--r-- | crates/libeditor/src/symbols.rs | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs deleted file mode 100644 index 2f9cc9233..000000000 --- a/crates/libeditor/src/symbols.rs +++ /dev/null | |||
@@ -1,167 +0,0 @@ | |||
1 | use libsyntax2::{ | ||
2 | SyntaxKind, SyntaxNodeRef, AstNode, File, SmolStr, | ||
3 | ast::{self, NameOwner}, | ||
4 | algo::{ | ||
5 | visit::{visitor, Visitor}, | ||
6 | walk::{walk, WalkEvent, preorder}, | ||
7 | }, | ||
8 | }; | ||
9 | use TextRange; | ||
10 | |||
11 | #[derive(Debug, Clone)] | ||
12 | pub struct StructureNode { | ||
13 | pub parent: Option<usize>, | ||
14 | pub label: String, | ||
15 | pub navigation_range: TextRange, | ||
16 | pub node_range: TextRange, | ||
17 | pub kind: SyntaxKind, | ||
18 | } | ||
19 | |||
20 | #[derive(Debug, Clone, Hash)] | ||
21 | pub struct FileSymbol { | ||
22 | pub name: SmolStr, | ||
23 | pub node_range: TextRange, | ||
24 | pub kind: SyntaxKind, | ||
25 | } | ||
26 | |||
27 | pub fn file_symbols(file: &File) -> Vec<FileSymbol> { | ||
28 | preorder(file.syntax()) | ||
29 | .filter_map(to_symbol) | ||
30 | .collect() | ||
31 | } | ||
32 | |||
33 | fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { | ||
34 | fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> { | ||
35 | let name = node.name()?; | ||
36 | Some(FileSymbol { | ||
37 | name: name.text(), | ||
38 | node_range: node.syntax().range(), | ||
39 | kind: node.syntax().kind(), | ||
40 | }) | ||
41 | } | ||
42 | visitor() | ||
43 | .visit(decl::<ast::FnDef>) | ||
44 | .visit(decl::<ast::StructDef>) | ||
45 | .visit(decl::<ast::EnumDef>) | ||
46 | .visit(decl::<ast::TraitDef>) | ||
47 | .visit(decl::<ast::Module>) | ||
48 | .visit(decl::<ast::TypeDef>) | ||
49 | .visit(decl::<ast::ConstDef>) | ||
50 | .visit(decl::<ast::StaticDef>) | ||
51 | .accept(node)? | ||
52 | } | ||
53 | |||
54 | |||
55 | pub fn file_structure(file: &File) -> Vec<StructureNode> { | ||
56 | let mut res = Vec::new(); | ||
57 | let mut stack = Vec::new(); | ||
58 | |||
59 | for event in walk(file.syntax()) { | ||
60 | match event { | ||
61 | WalkEvent::Enter(node) => { | ||
62 | match structure_node(node) { | ||
63 | Some(mut symbol) => { | ||
64 | symbol.parent = stack.last().map(|&n| n); | ||
65 | stack.push(res.len()); | ||
66 | res.push(symbol); | ||
67 | } | ||
68 | None => (), | ||
69 | } | ||
70 | } | ||
71 | WalkEvent::Exit(node) => { | ||
72 | if structure_node(node).is_some() { | ||
73 | stack.pop().unwrap(); | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | res | ||
79 | } | ||
80 | |||
81 | fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> { | ||
82 | fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<StructureNode> { | ||
83 | let name = node.name()?; | ||
84 | Some(StructureNode { | ||
85 | parent: None, | ||
86 | label: name.text().to_string(), | ||
87 | navigation_range: name.syntax().range(), | ||
88 | node_range: node.syntax().range(), | ||
89 | kind: node.syntax().kind(), | ||
90 | }) | ||
91 | } | ||
92 | |||
93 | visitor() | ||
94 | .visit(decl::<ast::FnDef>) | ||
95 | .visit(decl::<ast::StructDef>) | ||
96 | .visit(decl::<ast::NamedFieldDef>) | ||
97 | .visit(decl::<ast::EnumDef>) | ||
98 | .visit(decl::<ast::TraitDef>) | ||
99 | .visit(decl::<ast::Module>) | ||
100 | .visit(decl::<ast::TypeDef>) | ||
101 | .visit(decl::<ast::ConstDef>) | ||
102 | .visit(decl::<ast::StaticDef>) | ||
103 | .visit(|im: ast::ImplItem| { | ||
104 | let target_type = im.target_type()?; | ||
105 | let target_trait = im.target_trait(); | ||
106 | let label = match target_trait { | ||
107 | None => format!("impl {}", target_type.syntax().text()), | ||
108 | Some(t) => format!( | ||
109 | "impl {} for {}", | ||
110 | t.syntax().text(), | ||
111 | target_type.syntax().text(), | ||
112 | ), | ||
113 | }; | ||
114 | |||
115 | let node = StructureNode { | ||
116 | parent: None, | ||
117 | label, | ||
118 | navigation_range: target_type.syntax().range(), | ||
119 | node_range: im.syntax().range(), | ||
120 | kind: im.syntax().kind(), | ||
121 | }; | ||
122 | Some(node) | ||
123 | }) | ||
124 | .accept(node)? | ||
125 | } | ||
126 | |||
127 | #[cfg(test)] | ||
128 | mod tests { | ||
129 | use super::*; | ||
130 | use test_utils::assert_eq_dbg; | ||
131 | |||
132 | #[test] | ||
133 | fn test_file_structure() { | ||
134 | let file = File::parse(r#" | ||
135 | struct Foo { | ||
136 | x: i32 | ||
137 | } | ||
138 | |||
139 | mod m { | ||
140 | fn bar() {} | ||
141 | } | ||
142 | |||
143 | enum E { X, Y(i32) } | ||
144 | type T = (); | ||
145 | static S: i32 = 92; | ||
146 | const C: i32 = 92; | ||
147 | |||
148 | impl E {} | ||
149 | |||
150 | impl fmt::Debug for E {} | ||
151 | "#); | ||
152 | let symbols = file_structure(&file); | ||
153 | assert_eq_dbg( | ||
154 | r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF }, | ||
155 | StructureNode { parent: Some(0), label: "x", navigation_range: [18; 19), node_range: [18; 24), kind: NAMED_FIELD_DEF }, | ||
156 | StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE }, | ||
157 | StructureNode { parent: Some(2), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF }, | ||
158 | StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF }, | ||
159 | StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF }, | ||
160 | StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF }, | ||
161 | StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF }, | ||
162 | StructureNode { parent: None, label: "impl E", navigation_range: [134; 135), node_range: [129; 138), kind: IMPL_ITEM }, | ||
163 | StructureNode { parent: None, label: "impl fmt::Debug for E", navigation_range: [160; 161), node_range: [140; 164), kind: IMPL_ITEM }]"#, | ||
164 | &symbols, | ||
165 | ) | ||
166 | } | ||
167 | } | ||