embed file_id into FileSymbol

This commit is contained in:
Aleksey Kladov 2019-01-03 19:55:34 +03:00
parent 23d45177e2
commit 9bb2a74256
3 changed files with 34 additions and 35 deletions

View file

@ -165,9 +165,11 @@ impl db::RootDatabase {
}; };
} }
// If that fails try the index based approach. // If that fails try the index based approach.
for (file_id, symbol) in self.index_resolve(name_ref)? { rr.resolves_to.extend(
rr.add_resolution(file_id, symbol); self.index_resolve(name_ref)?
} .into_iter()
.map(NavigationTarget::from_symbol),
);
return Ok(Some(rr)); return Ok(Some(rr));
} }
if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
@ -352,13 +354,15 @@ impl db::RootDatabase {
// Resolve the function's NameRef (NOTE: this isn't entirely accurate). // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
let file_symbols = self.index_resolve(name_ref)?; let file_symbols = self.index_resolve(name_ref)?;
for (fn_file_id, fs) in file_symbols { for symbol in file_symbols {
if fs.ptr.kind() == FN_DEF { if symbol.ptr.kind() == FN_DEF {
let fn_file = self.source_file(fn_file_id); let fn_file = self.source_file(symbol.file_id);
let fn_def = fs.ptr.resolve(&fn_file); let fn_def = symbol.ptr.resolve(&fn_file);
let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap(); let fn_def = ast::FnDef::cast(fn_def.borrowed()).unwrap();
let descr = ctry!(source_binder::function_from_source( let descr = ctry!(source_binder::function_from_source(
self, fn_file_id, fn_def self,
symbol.file_id,
fn_def
)?); )?);
if let Some(descriptor) = descr.signature_info(self) { if let Some(descriptor) = descr.signature_info(self) {
// If we have a calling expression let's find which argument we are on // If we have a calling expression let's find which argument we are on
@ -438,7 +442,7 @@ impl db::RootDatabase {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
Ok(res) Ok(res)
} }
fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<(FileId, FileSymbol)>> { fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable<Vec<FileSymbol>> {
let name = name_ref.text(); let name = name_ref.text();
let mut query = Query::new(name.to_string()); let mut query = Query::new(name.to_string());
query.exact(); query.exact();

View file

@ -237,11 +237,11 @@ pub struct NavigationTarget {
} }
impl NavigationTarget { impl NavigationTarget {
fn from_symbol(file_id: FileId, symbol: FileSymbol) -> NavigationTarget { fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
NavigationTarget { NavigationTarget {
file_id: symbol.file_id,
name: symbol.name.clone(), name: symbol.name.clone(),
kind: symbol.ptr.kind(), kind: symbol.ptr.kind(),
file_id,
range: symbol.ptr.range(), range: symbol.ptr.range(),
ptr: Some(symbol.ptr.clone()), ptr: Some(symbol.ptr.clone()),
} }
@ -278,11 +278,6 @@ impl ReferenceResolution {
resolves_to: Vec::new(), resolves_to: Vec::new(),
} }
} }
fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
self.resolves_to
.push(NavigationTarget::from_symbol(file_id, symbol))
}
} }
/// `AnalysisHost` stores the current state of the world. /// `AnalysisHost` stores the current state of the world.
@ -380,7 +375,7 @@ impl Analysis {
pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
let res = symbol_index::world_symbols(&*self.db, query)? let res = symbol_index::world_symbols(&*self.db, query)?
.into_iter() .into_iter()
.map(|(file_id, symbol)| NavigationTarget::from_symbol(file_id, symbol)) .map(NavigationTarget::from_symbol)
.collect(); .collect();
Ok(res) Ok(res)
} }

View file

@ -58,10 +58,7 @@ fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Cancelable<Arc<Sym
Ok(Arc::new(SymbolIndex::for_file(file_id, syntax))) Ok(Arc::new(SymbolIndex::for_file(file_id, syntax)))
} }
pub(crate) fn world_symbols( pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Cancelable<Vec<FileSymbol>> {
db: &RootDatabase,
query: Query,
) -> Cancelable<Vec<(FileId, FileSymbol)>> {
/// Need to wrap Snapshot to provide `Clone` impl for `map_with` /// Need to wrap Snapshot to provide `Clone` impl for `map_with`
struct Snap(salsa::Snapshot<RootDatabase>); struct Snap(salsa::Snapshot<RootDatabase>);
impl Clone for Snap { impl Clone for Snap {
@ -95,7 +92,7 @@ pub(crate) fn world_symbols(
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub(crate) struct SymbolIndex { pub(crate) struct SymbolIndex {
symbols: Vec<(FileId, FileSymbol)>, symbols: Vec<FileSymbol>,
map: fst::Map, map: fst::Map,
} }
@ -126,14 +123,18 @@ impl SymbolIndex {
file.syntax() file.syntax()
.descendants() .descendants()
.filter_map(to_symbol) .filter_map(to_symbol)
.map(move |symbol| (symbol.name.as_str().to_lowercase(), (file_id, symbol))) .map(move |(name, ptr)| {
(
name.as_str().to_lowercase(),
FileSymbol { name, ptr, file_id },
)
})
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0)); symbols.par_sort_by(|s1, s2| s1.0.cmp(&s2.0));
symbols.dedup_by(|s1, s2| s1.0 == s2.0); symbols.dedup_by(|s1, s2| s1.0 == s2.0);
let (names, symbols): (Vec<String>, Vec<(FileId, FileSymbol)>) = let (names, symbols): (Vec<String>, Vec<FileSymbol>) = symbols.into_iter().unzip();
symbols.into_iter().unzip();
let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap(); let map = fst::Map::from_iter(names.into_iter().zip(0u64..)).unwrap();
SymbolIndex { symbols, map } SymbolIndex { symbols, map }
} }
@ -144,7 +145,7 @@ impl SymbolIndex {
} }
impl Query { impl Query {
pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<(FileId, FileSymbol)> { pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
let mut op = fst::map::OpBuilder::new(); let mut op = fst::map::OpBuilder::new();
for file_symbols in indices.iter() { for file_symbols in indices.iter() {
let automaton = fst::automaton::Subsequence::new(&self.lowercased); let automaton = fst::automaton::Subsequence::new(&self.lowercased);
@ -160,14 +161,14 @@ impl Query {
let file_symbols = &indices[indexed_value.index]; let file_symbols = &indices[indexed_value.index];
let idx = indexed_value.value as usize; let idx = indexed_value.value as usize;
let (file_id, symbol) = &file_symbols.symbols[idx]; let symbol = &file_symbols.symbols[idx];
if self.only_types && !is_type(symbol.ptr.kind()) { if self.only_types && !is_type(symbol.ptr.kind()) {
continue; continue;
} }
if self.exact && symbol.name != self.query { if self.exact && symbol.name != self.query {
continue; continue;
} }
res.push((*file_id, symbol.clone())); res.push(symbol.clone());
} }
} }
res res
@ -185,17 +186,16 @@ fn is_type(kind: SyntaxKind) -> bool {
/// possible. /// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct FileSymbol { pub(crate) struct FileSymbol {
pub(crate) file_id: FileId,
pub(crate) name: SmolStr, pub(crate) name: SmolStr,
pub(crate) ptr: LocalSyntaxPtr, pub(crate) ptr: LocalSyntaxPtr,
} }
fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { fn to_symbol(node: SyntaxNodeRef) -> Option<(SmolStr, LocalSyntaxPtr)> {
fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<FileSymbol> { fn decl<'a, N: NameOwner<'a>>(node: N) -> Option<(SmolStr, LocalSyntaxPtr)> {
let name = node.name()?; let name = node.name()?.text();
Some(FileSymbol { let ptr = LocalSyntaxPtr::new(node.syntax());
name: name.text(), Some((name, ptr))
ptr: LocalSyntaxPtr::new(node.syntax()),
})
} }
visitor() visitor()
.visit(decl::<ast::FnDef>) .visit(decl::<ast::FnDef>)