Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e728550

Browse files
committed
Restructure symbol queries
1 parent 9c40897 commit e728550

File tree

3 files changed

+56
-43
lines changed

3 files changed

+56
-43
lines changed

crates/hir/src/symbols.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,33 @@ pub struct SymbolCollector<'a> {
102102
/// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
103103
/// all symbols that should be indexed for the given module.
104104
impl<'a> SymbolCollector<'a> {
105-
pub fn collect(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> {
106-
let mut symbol_collector = SymbolCollector {
105+
pub fn new(db: &'a dyn HirDatabase) -> Self {
106+
SymbolCollector {
107107
db,
108108
symbols: Default::default(),
109+
work: Default::default(),
109110
current_container_name: None,
110-
// The initial work is the root module we're collecting, additional work will
111-
// be populated as we traverse the module's definitions.
112-
work: vec![SymbolCollectorWork { module_id: module.into(), parent: None }],
113-
};
111+
}
112+
}
113+
114+
pub fn collect(&mut self, module: Module) {
115+
// The initial work is the root module we're collecting, additional work will
116+
// be populated as we traverse the module's definitions.
117+
self.work.push(SymbolCollectorWork { module_id: module.into(), parent: None });
114118

115-
while let Some(work) = symbol_collector.work.pop() {
116-
symbol_collector.do_work(work);
119+
while let Some(work) = self.work.pop() {
120+
self.do_work(work);
117121
}
122+
}
123+
124+
pub fn finish(self) -> Vec<FileSymbol> {
125+
self.symbols
126+
}
118127

119-
symbol_collector.symbols
128+
pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> {
129+
let mut symbol_collector = SymbolCollector::new(db);
130+
symbol_collector.collect(module);
131+
symbol_collector.finish()
120132
}
121133

122134
fn do_work(&mut self, work: SymbolCollectorWork) {

crates/ide-db/src/items_locator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ fn find_items<'a>(
115115
});
116116

117117
// Query the local crate using the symbol index.
118-
let local_results = symbol_index::crate_symbols(db, krate, local_query)
118+
let local_results = local_query
119+
.search(&symbol_index::crate_symbols(db, krate))
119120
.into_iter()
120121
.filter_map(move |local_candidate| get_name_definition(sema, &local_candidate))
121122
.filter_map(|name_definition_to_import| match name_definition_to_import {

crates/ide-db/src/symbol_index.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,15 @@ impl Query {
9393
pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatabase> {
9494
/// The symbol index for a given module. These modules should only be in source roots that
9595
/// are inside local_roots.
96-
// FIXME: We should probably LRU this
9796
fn module_symbols(&self, module: Module) -> Arc<SymbolIndex>;
9897

9998
/// The symbol index for a given source root within library_roots.
10099
fn library_symbols(&self, source_root_id: SourceRootId) -> Arc<SymbolIndex>;
101100

101+
#[salsa::transparent]
102+
/// The symbol indices of modules that make up a given crate.
103+
fn crate_symbols(&self, krate: Crate) -> Box<[Arc<SymbolIndex>]>;
104+
102105
/// The set of "local" (that is, from the current workspace) roots.
103106
/// Files in local roots are assumed to change frequently.
104107
#[salsa::input]
@@ -113,26 +116,33 @@ pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatab
113116
fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Arc<SymbolIndex> {
114117
let _p = profile::span("library_symbols");
115118

116-
// todo: this could be parallelized, once I figure out how to do that...
117-
let symbols = db
118-
.source_root_crates(source_root_id)
119+
let mut symbol_collector = SymbolCollector::new(db.upcast());
120+
121+
db.source_root_crates(source_root_id)
119122
.iter()
120123
.flat_map(|&krate| Crate::from(krate).modules(db.upcast()))
121-
// we specifically avoid calling SymbolsDatabase::module_symbols here, even they do the same thing,
124+
// we specifically avoid calling other SymbolsDatabase queries here, even though they do the same thing,
122125
// as the index for a library is not going to really ever change, and we do not want to store each
123-
// module's index in salsa.
124-
.flat_map(|module| SymbolCollector::collect(db.upcast(), module))
125-
.collect();
126+
// the module or crate indices for those in salsa unless we need to.
127+
.for_each(|module| symbol_collector.collect(module));
126128

129+
let mut symbols = symbol_collector.finish();
130+
symbols.shrink_to_fit();
127131
Arc::new(SymbolIndex::new(symbols))
128132
}
129133

130134
fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
131135
let _p = profile::span("module_symbols");
132-
let symbols = SymbolCollector::collect(db.upcast(), module);
136+
137+
let symbols = SymbolCollector::collect_module(db.upcast(), module);
133138
Arc::new(SymbolIndex::new(symbols))
134139
}
135140

141+
pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
142+
let _p = profile::span("crate_symbols");
143+
krate.modules(db.upcast()).into_iter().map(|module| db.module_symbols(module)).collect()
144+
}
145+
136146
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
137147
struct Snap<DB>(DB);
138148
impl<DB: ParallelDatabase> Snap<salsa::Snapshot<DB>> {
@@ -188,36 +198,21 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
188198
.map_with(Snap::new(db), |snap, &root| snap.library_symbols(root))
189199
.collect()
190200
} else {
191-
let mut modules = Vec::new();
201+
let mut crates = Vec::new();
192202

193203
for &root in db.local_roots().iter() {
194-
let crates = db.source_root_crates(root);
195-
for &krate in crates.iter() {
196-
modules.extend(Crate::from(krate).modules(db));
197-
}
204+
crates.extend(db.source_root_crates(root).iter().copied())
198205
}
199-
200-
modules
201-
.par_iter()
202-
.map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
203-
.collect()
206+
let indices: Vec<_> = crates
207+
.into_par_iter()
208+
.map_with(Snap::new(db), |snap, krate| snap.crate_symbols(krate.into()))
209+
.collect();
210+
indices.iter().flat_map(|indices| indices.iter().cloned()).collect()
204211
};
205212

206213
query.search(&indices)
207214
}
208215

209-
pub fn crate_symbols(db: &RootDatabase, krate: Crate, query: Query) -> Vec<FileSymbol> {
210-
let _p = profile::span("crate_symbols").detail(|| format!("{query:?}"));
211-
212-
let modules = krate.modules(db);
213-
let indices: Vec<_> = modules
214-
.par_iter()
215-
.map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
216-
.collect();
217-
218-
query.search(&indices)
219-
}
220-
221216
#[derive(Default)]
222217
pub struct SymbolIndex {
223218
symbols: Vec<FileSymbol>,
@@ -275,7 +270,12 @@ impl SymbolIndex {
275270
builder.insert(key, value).unwrap();
276271
}
277272

278-
let map = fst::Map::new(builder.into_inner().unwrap()).unwrap();
273+
let map = fst::Map::new({
274+
let mut buf = builder.into_inner().unwrap();
275+
buf.shrink_to_fit();
276+
buf
277+
})
278+
.unwrap();
279279
SymbolIndex { symbols, map }
280280
}
281281

@@ -419,7 +419,7 @@ struct StructInModB;
419419
.modules(&db)
420420
.into_iter()
421421
.map(|module_id| {
422-
let mut symbols = SymbolCollector::collect(&db, module_id);
422+
let mut symbols = SymbolCollector::collect_module(&db, module_id);
423423
symbols.sort_by_key(|it| it.name.clone());
424424
(module_id, symbols)
425425
})

0 commit comments

Comments
 (0)