Add support for container_name in workspace/symbol query

This commit is contained in:
Ville Penttinen 2019-02-12 21:47:51 +02:00
parent 61324a845b
commit dd6307ddc4
4 changed files with 116 additions and 17 deletions

View file

@ -19,6 +19,7 @@ pub struct NavigationTarget {
kind: SyntaxKind,
full_range: TextRange,
focus_range: Option<TextRange>,
container_name: Option<SmolStr>,
}
impl NavigationTarget {
@ -26,6 +27,10 @@ impl NavigationTarget {
&self.name
}
pub fn container_name(&self) -> Option<&SmolStr> {
self.container_name.as_ref()
}
pub fn kind(&self) -> SyntaxKind {
self.kind
}
@ -53,6 +58,7 @@ impl NavigationTarget {
kind: symbol.ptr.kind(),
full_range: symbol.ptr.range(),
focus_range: None,
container_name: symbol.container_name.map(|v| v.clone()),
}
}
@ -67,6 +73,7 @@ impl NavigationTarget {
full_range: ptr.range(),
focus_range: None,
kind: NAME,
container_name: None,
}
}
@ -170,6 +177,9 @@ impl NavigationTarget {
if let Some(focus_range) = self.focus_range() {
buf.push_str(&format!(" {:?}", focus_range))
}
if let Some(container_name) = self.container_name() {
buf.push_str(&format!(" {:?}", container_name))
}
buf
}
@ -192,6 +202,7 @@ impl NavigationTarget {
full_range: node.range(),
focus_range,
// ptr: Some(LocalSyntaxPtr::new(node)),
container_name: None,
}
}
}

View file

@ -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<SymbolIndex> {
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::<Vec<_>>();
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<Item = (FileId, TreeArc<SourceFile>)>,
) -> 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::<Vec<_>>()
})
.flat_map(|(file_id, file)| source_file_to_file_symbols(&file, file_id))
.collect::<Vec<_>>();
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<SmolStr>,
}
fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
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<N: NameOwner>(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::<ast::StaticDef>)
.accept(node)?
}
fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
to_symbol(node).map(move |(name, ptr)| FileSymbol { name, ptr, file_id, container_name: None })
}