aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/symbol_index.rs
diff options
context:
space:
mode:
authorVille Penttinen <[email protected]>2019-02-12 19:47:51 +0000
committerVille Penttinen <[email protected]>2019-02-12 20:06:14 +0000
commitdd6307ddc4535bef09e2b14caff5acfaeb88891e (patch)
tree4e1511826adb09561572ed8eb405f0ad8d84f42a /crates/ra_ide_api/src/symbol_index.rs
parent61324a845bde0959c1f9ac86ce31d022812f4c21 (diff)
Add support for container_name in workspace/symbol query
Diffstat (limited to 'crates/ra_ide_api/src/symbol_index.rs')
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs62
1 files changed, 48 insertions, 14 deletions
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index 15348124b..62d0979fe 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -32,6 +32,7 @@ use ra_syntax::{
32 algo::{visit::{visitor, Visitor}, find_covering_node}, 32 algo::{visit::{visitor, Visitor}, find_covering_node},
33 SyntaxKind::{self, *}, 33 SyntaxKind::{self, *},
34 ast::{self, NameOwner}, 34 ast::{self, NameOwner},
35 WalkEvent,
35}; 36};
36use ra_db::{ 37use ra_db::{
37 SourceRootId, SourceDatabase, 38 SourceRootId, SourceDatabase,
@@ -62,17 +63,14 @@ pub(crate) trait SymbolsDatabase: hir::db::HirDatabase {
62fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { 63fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> {
63 db.check_canceled(); 64 db.check_canceled();
64 let source_file = db.parse(file_id); 65 let source_file = db.parse(file_id);
65 let mut symbols = source_file 66
66 .syntax() 67 let mut symbols = source_file_to_file_symbols(&source_file, file_id);
67 .descendants()
68 .filter_map(to_symbol)
69 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
70 .collect::<Vec<_>>();
71 68
72 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) { 69 for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) {
73 let node = find_covering_node(source_file.syntax(), text_range); 70 let node = find_covering_node(source_file.syntax(), text_range);
74 let ptr = SyntaxNodePtr::new(node); 71 let ptr = SyntaxNodePtr::new(node);
75 symbols.push(FileSymbol { file_id, name, ptr }) 72 // TODO: Should we get container name for macro symbols?
73 symbols.push(FileSymbol { file_id, name, ptr, container_name: None })
76 } 74 }
77 75
78 Arc::new(SymbolIndex::new(symbols)) 76 Arc::new(SymbolIndex::new(symbols))
@@ -158,13 +156,7 @@ impl SymbolIndex {
158 files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>, 156 files: impl ParallelIterator<Item = (FileId, TreeArc<SourceFile>)>,
159 ) -> SymbolIndex { 157 ) -> SymbolIndex {
160 let symbols = files 158 let symbols = files
161 .flat_map(|(file_id, file)| { 159 .flat_map(|(file_id, file)| source_file_to_file_symbols(&file, file_id))
162 file.syntax()
163 .descendants()
164 .filter_map(to_symbol)
165 .map(move |(name, ptr)| FileSymbol { name, ptr, file_id })
166 .collect::<Vec<_>>()
167 })
168 .collect::<Vec<_>>(); 160 .collect::<Vec<_>>();
169 SymbolIndex::new(symbols) 161 SymbolIndex::new(symbols)
170 } 162 }
@@ -208,6 +200,16 @@ fn is_type(kind: SyntaxKind) -> bool {
208 } 200 }
209} 201}
210 202
203fn is_symbol_def(kind: SyntaxKind) -> bool {
204 match kind {
205 FN_DEF | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | MODULE | TYPE_DEF | CONST_DEF | STATIC_DEF => {
206 true
207 }
208
209 _ => false,
210 }
211}
212
211/// The actual data that is stored in the index. It should be as compact as 213/// The actual data that is stored in the index. It should be as compact as
212/// possible. 214/// possible.
213#[derive(Debug, Clone, PartialEq, Eq, Hash)] 215#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -215,12 +217,40 @@ pub(crate) struct FileSymbol {
215 pub(crate) file_id: FileId, 217 pub(crate) file_id: FileId,
216 pub(crate) name: SmolStr, 218 pub(crate) name: SmolStr,
217 pub(crate) ptr: SyntaxNodePtr, 219 pub(crate) ptr: SyntaxNodePtr,
220 pub(crate) container_name: Option<SmolStr>,
221}
222
223fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
224 let mut symbols = Vec::new();
225 let mut stack = Vec::new();
226
227 for event in source_file.syntax().preorder() {
228 match event {
229 WalkEvent::Enter(node) => {
230 if let Some(mut symbol) = to_file_symbol(node, file_id) {
231 symbol.container_name = stack.last().map(|v: &SmolStr| v.clone());
232
233 stack.push(symbol.name.clone());
234 symbols.push(symbol);
235 }
236 }
237
238 WalkEvent::Leave(node) => {
239 if is_symbol_def(node.kind()) {
240 stack.pop();
241 }
242 }
243 }
244 }
245
246 symbols
218} 247}
219 248
220fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { 249fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> {
221 fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { 250 fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> {
222 let name = node.name()?.text().clone(); 251 let name = node.name()?.text().clone();
223 let ptr = SyntaxNodePtr::new(node.syntax()); 252 let ptr = SyntaxNodePtr::new(node.syntax());
253
224 Some((name, ptr)) 254 Some((name, ptr))
225 } 255 }
226 visitor() 256 visitor()
@@ -234,3 +264,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> {
234 .visit(decl::<ast::StaticDef>) 264 .visit(decl::<ast::StaticDef>)
235 .accept(node)? 265 .accept(node)?
236} 266}
267
268fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
269 to_symbol(node).map(move |(name, ptr)| FileSymbol { name, ptr, file_id, container_name: None })
270}