Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/symbol_index.rs')
| -rw-r--r-- | crates/ide-db/src/symbol_index.rs | 103 |
1 files changed, 69 insertions, 34 deletions
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index a91ffd1ec4..b54c43b296 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -25,7 +25,6 @@ use std::{ fmt, hash::{Hash, Hasher}, mem, - sync::Arc, }; use base_db::{ @@ -40,6 +39,7 @@ use hir::{ }; use rayon::prelude::*; use rustc_hash::FxHashSet; +use triomphe::Arc; use crate::RootDatabase; @@ -98,6 +98,10 @@ pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatab /// The symbol index for a given source root within library_roots. fn library_symbols(&self, source_root_id: SourceRootId) -> Arc<SymbolIndex>; + #[salsa::transparent] + /// The symbol indices of modules that make up a given crate. + fn crate_symbols(&self, krate: Crate) -> Box<[Arc<SymbolIndex>]>; + /// The set of "local" (that is, from the current workspace) roots. /// Files in local roots are assumed to change frequently. #[salsa::input] @@ -112,26 +116,33 @@ pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatab fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Arc<SymbolIndex> { let _p = profile::span("library_symbols"); - // todo: this could be parallelized, once I figure out how to do that... - let symbols = db - .source_root_crates(source_root_id) + let mut symbol_collector = SymbolCollector::new(db.upcast()); + + db.source_root_crates(source_root_id) .iter() .flat_map(|&krate| Crate::from(krate).modules(db.upcast())) - // we specifically avoid calling SymbolsDatabase::module_symbols here, even they do the same thing, + // we specifically avoid calling other SymbolsDatabase queries here, even though they do the same thing, // as the index for a library is not going to really ever change, and we do not want to store each - // module's index in salsa. - .flat_map(|module| SymbolCollector::collect(db.upcast(), module)) - .collect(); + // the module or crate indices for those in salsa unless we need to. + .for_each(|module| symbol_collector.collect(module)); + let mut symbols = symbol_collector.finish(); + symbols.shrink_to_fit(); Arc::new(SymbolIndex::new(symbols)) } fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> { let _p = profile::span("module_symbols"); - let symbols = SymbolCollector::collect(db.upcast(), module); + + let symbols = SymbolCollector::collect_module(db.upcast(), module); Arc::new(SymbolIndex::new(symbols)) } +pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> { + let _p = profile::span("crate_symbols"); + krate.modules(db.upcast()).into_iter().map(|module| db.module_symbols(module)).collect() +} + /// Need to wrap Snapshot to provide `Clone` impl for `map_with` struct Snap<DB>(DB); impl<DB: ParallelDatabase> Snap<salsa::Snapshot<DB>> { @@ -187,36 +198,21 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { .map_with(Snap::new(db), |snap, &root| snap.library_symbols(root)) .collect() } else { - let mut modules = Vec::new(); + let mut crates = Vec::new(); for &root in db.local_roots().iter() { - let crates = db.source_root_crates(root); - for &krate in crates.iter() { - modules.extend(Crate::from(krate).modules(db)); - } + crates.extend(db.source_root_crates(root).iter().copied()) } - - modules - .par_iter() - .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module)) - .collect() + let indices: Vec<_> = crates + .into_par_iter() + .map_with(Snap::new(db), |snap, krate| snap.crate_symbols(krate.into())) + .collect(); + indices.iter().flat_map(|indices| indices.iter().cloned()).collect() }; query.search(&indices) } -pub fn crate_symbols(db: &RootDatabase, krate: Crate, query: Query) -> Vec<FileSymbol> { - let _p = profile::span("crate_symbols").detail(|| format!("{query:?}")); - - let modules = krate.modules(db); - let indices: Vec<_> = modules - .par_iter() - .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module)) - .collect(); - - query.search(&indices) -} - #[derive(Default)] pub struct SymbolIndex { symbols: Vec<FileSymbol>, @@ -274,7 +270,12 @@ impl SymbolIndex { builder.insert(key, value).unwrap(); } - let map = fst::Map::new(builder.into_inner().unwrap()).unwrap(); + let map = fst::Map::new({ + let mut buf = builder.into_inner().unwrap(); + buf.shrink_to_fit(); + buf + }) + .unwrap(); SymbolIndex { symbols, map } } @@ -316,7 +317,14 @@ impl Query { let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value); for symbol in &symbol_index.symbols[start..end] { - if self.only_types && !symbol.kind.is_type() { + if self.only_types + && !matches!( + symbol.def, + hir::ModuleDef::Adt(..) + | hir::ModuleDef::TypeAlias(..) + | hir::ModuleDef::BuiltinType(..) + ) + { continue; } if self.exact { @@ -418,7 +426,7 @@ struct StructInModB; .modules(&db) .into_iter() .map(|module_id| { - let mut symbols = SymbolCollector::collect(&db, module_id); + let mut symbols = SymbolCollector::collect_module(&db, module_id); symbols.sort_by_key(|it| it.name.clone()); (module_id, symbols) }) @@ -426,4 +434,31 @@ struct StructInModB; expect_file!["./test_data/test_symbol_index_collection.txt"].assert_debug_eq(&symbols); } + + #[test] + fn test_doc_alias() { + let (db, _) = RootDatabase::with_single_file( + r#" +#[doc(alias="s1")] +#[doc(alias="s2")] +#[doc(alias("mul1","mul2"))] +struct Struct; + +#[doc(alias="s1")] +struct Duplicate; + "#, + ); + + let symbols: Vec<_> = Crate::from(db.test_crate()) + .modules(&db) + .into_iter() + .map(|module_id| { + let mut symbols = SymbolCollector::collect_module(&db, module_id); + symbols.sort_by_key(|it| it.name.clone()); + (module_id, symbols) + }) + .collect(); + + expect_file!["./test_data/test_doc_alias.txt"].assert_debug_eq(&symbols); + } } |