From dd6307ddc4535bef09e2b14caff5acfaeb88891e Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Tue, 12 Feb 2019 21:47:51 +0200 Subject: Add support for container_name in workspace/symbol query --- crates/ra_ide_api/src/symbol_index.rs | 62 +++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 14 deletions(-) (limited to 'crates/ra_ide_api/src/symbol_index.rs') 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::{ algo::{visit::{visitor, Visitor}, find_covering_node}, SyntaxKind::{self, *}, ast::{self, NameOwner}, + WalkEvent, }; use ra_db::{ SourceRootId, SourceDatabase, @@ -62,17 +63,14 @@ pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc { db.check_canceled(); let source_file = db.parse(file_id); - let mut symbols = source_file - .syntax() - .descendants() - .filter_map(to_symbol) - .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) - .collect::>(); + + let mut symbols = source_file_to_file_symbols(&source_file, file_id); for (name, text_range) in hir::source_binder::macro_symbols(db, file_id) { let node = find_covering_node(source_file.syntax(), text_range); let ptr = SyntaxNodePtr::new(node); - symbols.push(FileSymbol { file_id, name, ptr }) + // TODO: Should we get container name for macro symbols? + symbols.push(FileSymbol { file_id, name, ptr, container_name: None }) } Arc::new(SymbolIndex::new(symbols)) @@ -158,13 +156,7 @@ impl SymbolIndex { files: impl ParallelIterator)>, ) -> SymbolIndex { let symbols = files - .flat_map(|(file_id, file)| { - file.syntax() - .descendants() - .filter_map(to_symbol) - .map(move |(name, ptr)| FileSymbol { name, ptr, file_id }) - .collect::>() - }) + .flat_map(|(file_id, file)| source_file_to_file_symbols(&file, file_id)) .collect::>(); SymbolIndex::new(symbols) } @@ -208,6 +200,16 @@ fn is_type(kind: SyntaxKind) -> bool { } } +fn is_symbol_def(kind: SyntaxKind) -> bool { + match kind { + FN_DEF | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | MODULE | TYPE_DEF | CONST_DEF | STATIC_DEF => { + true + } + + _ => false, + } +} + /// The actual data that is stored in the index. It should be as compact as /// possible. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -215,12 +217,40 @@ pub(crate) struct FileSymbol { pub(crate) file_id: FileId, pub(crate) name: SmolStr, pub(crate) ptr: SyntaxNodePtr, + pub(crate) container_name: Option, +} + +fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec { + let mut symbols = Vec::new(); + let mut stack = Vec::new(); + + for event in source_file.syntax().preorder() { + match event { + WalkEvent::Enter(node) => { + if let Some(mut symbol) = to_file_symbol(node, file_id) { + symbol.container_name = stack.last().map(|v: &SmolStr| v.clone()); + + stack.push(symbol.name.clone()); + symbols.push(symbol); + } + } + + WalkEvent::Leave(node) => { + if is_symbol_def(node.kind()) { + stack.pop(); + } + } + } + } + + symbols } fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { fn decl(node: &N) -> Option<(SmolStr, SyntaxNodePtr)> { let name = node.name()?.text().clone(); let ptr = SyntaxNodePtr::new(node.syntax()); + Some((name, ptr)) } visitor() @@ -234,3 +264,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr)> { .visit(decl::) .accept(node)? } + +fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option { + to_symbol(node).map(move |(name, ptr)| FileSymbol { name, ptr, file_id, container_name: None }) +} -- cgit v1.2.3