diff options
Diffstat (limited to 'crates/ra_ide_api/src/symbol_index.rs')
-rw-r--r-- | crates/ra_ide_api/src/symbol_index.rs | 52 |
1 files changed, 38 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..afb10fa92 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 | }; |
36 | use ra_db::{ | 37 | use ra_db::{ |
37 | SourceRootId, SourceDatabase, | 38 | SourceRootId, SourceDatabase, |
@@ -62,17 +63,14 @@ pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { | |||
62 | fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 63 | fn 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 | } |
@@ -215,12 +207,40 @@ pub(crate) struct FileSymbol { | |||
215 | pub(crate) file_id: FileId, | 207 | pub(crate) file_id: FileId, |
216 | pub(crate) name: SmolStr, | 208 | pub(crate) name: SmolStr, |
217 | pub(crate) ptr: SyntaxNodePtr, | 209 | pub(crate) ptr: SyntaxNodePtr, |
210 | pub(crate) container_name: Option<SmolStr>, | ||
211 | } | ||
212 | |||
213 | fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> { | ||
214 | let mut symbols = Vec::new(); | ||
215 | let mut stack = Vec::new(); | ||
216 | |||
217 | for event in source_file.syntax().preorder() { | ||
218 | match event { | ||
219 | WalkEvent::Enter(node) => { | ||
220 | if let Some(mut symbol) = to_file_symbol(node, file_id) { | ||
221 | symbol.container_name = stack.last().cloned(); | ||
222 | |||
223 | stack.push(symbol.name.clone()); | ||
224 | symbols.push(symbol); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | WalkEvent::Leave(node) => { | ||
229 | if to_symbol(node).is_some() { | ||
230 | stack.pop(); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | symbols | ||
218 | } | 237 | } |
219 | 238 | ||
220 | fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { | 239 | fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { |
221 | fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { | 240 | fn decl<N: NameOwner>(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { |
222 | let name = node.name()?.text().clone(); | 241 | let name = node.name()?.text().clone(); |
223 | let ptr = SyntaxNodePtr::new(node.syntax()); | 242 | let ptr = SyntaxNodePtr::new(node.syntax()); |
243 | |||
224 | Some((name, ptr)) | 244 | Some((name, ptr)) |
225 | } | 245 | } |
226 | visitor() | 246 | visitor() |
@@ -234,3 +254,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { | |||
234 | .visit(decl::<ast::StaticDef>) | 254 | .visit(decl::<ast::StaticDef>) |
235 | .accept(node)? | 255 | .accept(node)? |
236 | } | 256 | } |
257 | |||
258 | fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> { | ||
259 | to_symbol(node).map(move |(name, ptr)| FileSymbol { name, ptr, file_id, container_name: None }) | ||
260 | } | ||