mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-27 16:07:46 +00:00
Disassemble SymbolsDatabase
This commit is contained in:
parent
abf2e3ed15
commit
3c19ebf63a
@ -35,6 +35,9 @@ pub mod term_search;
|
||||
|
||||
mod display;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use hir_def::ModuleId;
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
mem::discriminant,
|
||||
@ -48,8 +51,8 @@ use hir_def::{
|
||||
AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
|
||||
CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId,
|
||||
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
||||
LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, SyntheticSyntax,
|
||||
TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
||||
LocalFieldId, Lookup, MacroExpander, MacroId, StaticId, StructId, SyntheticSyntax, TupleId,
|
||||
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
||||
expr_store::{ExpressionStoreDiagnostics, ExpressionStoreSourceMap},
|
||||
hir::{
|
||||
BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat,
|
||||
|
||||
@ -3,10 +3,12 @@
|
||||
use base_db::SourceRootId;
|
||||
use profile::Bytes;
|
||||
use rustc_hash::FxHashSet;
|
||||
use salsa::{Database as _, Durability};
|
||||
use triomphe::Arc;
|
||||
use salsa::{Database as _, Durability, Setter as _};
|
||||
|
||||
use crate::{ChangeWithProcMacros, RootDatabase, symbol_index::SymbolsDatabase};
|
||||
use crate::{
|
||||
ChangeWithProcMacros, RootDatabase,
|
||||
symbol_index::{LibraryRoots, LocalRoots},
|
||||
};
|
||||
|
||||
impl RootDatabase {
|
||||
pub fn request_cancellation(&mut self) {
|
||||
@ -29,8 +31,8 @@ impl RootDatabase {
|
||||
local_roots.insert(root_id);
|
||||
}
|
||||
}
|
||||
self.set_local_roots_with_durability(Arc::new(local_roots), Durability::MEDIUM);
|
||||
self.set_library_roots_with_durability(Arc::new(library_roots), Durability::MEDIUM);
|
||||
LocalRoots::get(self).set_roots(self).to(local_roots);
|
||||
LibraryRoots::get(self).set_roots(self).to(library_roots);
|
||||
}
|
||||
change.apply(self);
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ use hir::{Complete, Crate, ItemInNs, Module, import_map};
|
||||
use crate::{
|
||||
RootDatabase,
|
||||
imports::import_assets::NameToImport,
|
||||
symbol_index::{self, SymbolsDatabase as _},
|
||||
symbol_index::{self, SymbolIndex},
|
||||
};
|
||||
|
||||
/// A value to use, when uncertain which limit to pick.
|
||||
@ -110,7 +110,7 @@ pub fn items_with_name_in_module<T>(
|
||||
local_query
|
||||
}
|
||||
};
|
||||
local_query.search(&[db.module_symbols(module)], |local_candidate| {
|
||||
local_query.search(&[SymbolIndex::module_symbols(db, module)], |local_candidate| {
|
||||
cb(match local_candidate.def {
|
||||
hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
|
||||
def => ItemInNs::from(def),
|
||||
|
||||
@ -64,7 +64,7 @@ use hir::{
|
||||
};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
|
||||
use crate::line_index::LineIndex;
|
||||
pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
|
||||
|
||||
pub use ::line_index;
|
||||
@ -195,8 +195,12 @@ impl RootDatabase {
|
||||
db.set_all_crates(Arc::new(Box::new([])));
|
||||
CrateGraphBuilder::default().set_in_db(&mut db);
|
||||
db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM);
|
||||
db.set_local_roots_with_durability(Default::default(), Durability::MEDIUM);
|
||||
db.set_library_roots_with_durability(Default::default(), Durability::MEDIUM);
|
||||
_ = crate::symbol_index::LibraryRoots::builder(Default::default())
|
||||
.durability(Durability::MEDIUM)
|
||||
.new(&db);
|
||||
_ = crate::symbol_index::LocalRoots::builder(Default::default())
|
||||
.durability(Durability::MEDIUM)
|
||||
.new(&db);
|
||||
db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH);
|
||||
db.update_base_query_lru_capacities(lru_capacity);
|
||||
db
|
||||
|
||||
@ -11,7 +11,7 @@ use salsa::{Cancelled, Database};
|
||||
use crate::{
|
||||
FxIndexMap, RootDatabase,
|
||||
base_db::{Crate, RootQueryDb},
|
||||
symbol_index::SymbolsDatabase,
|
||||
symbol_index::SymbolIndex,
|
||||
};
|
||||
|
||||
/// We're indexing many crates.
|
||||
@ -107,8 +107,9 @@ pub fn parallel_prime_caches(
|
||||
Ok::<_, crossbeam_channel::SendError<_>>(())
|
||||
};
|
||||
let handle_symbols = |module| {
|
||||
let cancelled =
|
||||
Cancelled::catch(AssertUnwindSafe(|| _ = db.module_symbols(module)));
|
||||
let cancelled = Cancelled::catch(AssertUnwindSafe(|| {
|
||||
_ = SymbolIndex::module_symbols(&db, module)
|
||||
}));
|
||||
|
||||
match cancelled {
|
||||
Ok(()) => progress_sender
|
||||
|
||||
@ -27,7 +27,7 @@ use std::{
|
||||
ops::ControlFlow,
|
||||
};
|
||||
|
||||
use base_db::{RootQueryDb, SourceDatabase, SourceRootId};
|
||||
use base_db::{RootQueryDb, SourceRootId};
|
||||
use fst::{Automaton, Streamer, raw::IndexedValue};
|
||||
use hir::{
|
||||
Crate, Module,
|
||||
@ -37,7 +37,6 @@ use hir::{
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use rustc_hash::FxHashSet;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::RootDatabase;
|
||||
|
||||
@ -102,63 +101,26 @@ impl Query {
|
||||
}
|
||||
}
|
||||
|
||||
#[query_group::query_group]
|
||||
pub trait SymbolsDatabase: HirDatabase + SourceDatabase {
|
||||
/// The symbol index for a given module. These modules should only be in source roots that
|
||||
/// are inside local_roots.
|
||||
// FIXME: Is it worth breaking the encapsulation boundary of `hir`, and make this take a `ModuleId`,
|
||||
// in order for it to be a non-interned query?
|
||||
#[salsa::invoke_interned(module_symbols)]
|
||||
fn module_symbols(&self, module: Module) -> Arc<SymbolIndex>;
|
||||
|
||||
/// The symbol index for a given source root within library_roots.
|
||||
#[salsa::invoke_interned(library_symbols)]
|
||||
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]
|
||||
fn local_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
|
||||
|
||||
/// The set of roots for crates.io libraries.
|
||||
/// Files in libraries are assumed to never change.
|
||||
#[salsa::input]
|
||||
fn library_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
|
||||
/// The set of roots for crates.io libraries.
|
||||
/// Files in libraries are assumed to never change.
|
||||
#[salsa::input(singleton, debug)]
|
||||
pub struct LibraryRoots {
|
||||
#[returns(ref)]
|
||||
pub roots: FxHashSet<SourceRootId>,
|
||||
}
|
||||
|
||||
fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Arc<SymbolIndex> {
|
||||
let _p = tracing::info_span!("library_symbols").entered();
|
||||
|
||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||
hir::attach_db(db, || {
|
||||
let mut symbol_collector = SymbolCollector::new(db);
|
||||
|
||||
db.source_root_crates(source_root_id)
|
||||
.iter()
|
||||
.flat_map(|&krate| Crate::from(krate).modules(db))
|
||||
// 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
|
||||
// the module or crate indices for those in salsa unless we need to.
|
||||
.for_each(|module| symbol_collector.collect(module));
|
||||
|
||||
Arc::new(SymbolIndex::new(symbol_collector.finish()))
|
||||
})
|
||||
/// The set of "local" (that is, from the current workspace) roots.
|
||||
/// Files in local roots are assumed to change frequently.
|
||||
#[salsa::input(singleton, debug)]
|
||||
pub struct LocalRoots {
|
||||
#[returns(ref)]
|
||||
pub roots: FxHashSet<SourceRootId>,
|
||||
}
|
||||
|
||||
fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
|
||||
let _p = tracing::info_span!("module_symbols").entered();
|
||||
|
||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||
hir::attach_db(db, || Arc::new(SymbolIndex::new(SymbolCollector::new_module(db, module))))
|
||||
}
|
||||
|
||||
pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
|
||||
/// The symbol indices of modules that make up a given crate.
|
||||
pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex]> {
|
||||
let _p = tracing::info_span!("crate_symbols").entered();
|
||||
krate.modules(db).into_iter().map(|module| db.module_symbols(module)).collect()
|
||||
krate.modules(db).into_iter().map(|module| SymbolIndex::module_symbols(db, module)).collect()
|
||||
}
|
||||
|
||||
// Feature: Workspace Symbol
|
||||
@ -190,20 +152,26 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
|
||||
let _p = tracing::info_span!("world_symbols", query = ?query.query).entered();
|
||||
|
||||
let indices: Vec<_> = if query.libs {
|
||||
db.library_roots()
|
||||
LibraryRoots::get(db)
|
||||
.roots(db)
|
||||
.par_iter()
|
||||
.map_with(db.clone(), |snap, &root| snap.library_symbols(root))
|
||||
.for_each_with(db.clone(), |snap, &root| _ = SymbolIndex::library_symbols(snap, root));
|
||||
LibraryRoots::get(db)
|
||||
.roots(db)
|
||||
.iter()
|
||||
.map(|&root| SymbolIndex::library_symbols(db, root))
|
||||
.collect()
|
||||
} else {
|
||||
let mut crates = Vec::new();
|
||||
|
||||
for &root in db.local_roots().iter() {
|
||||
for &root in LocalRoots::get(db).roots(db).iter() {
|
||||
crates.extend(db.source_root_crates(root).iter().copied())
|
||||
}
|
||||
let indices: Vec<_> = crates
|
||||
.into_par_iter()
|
||||
.map_with(db.clone(), |snap, krate| snap.crate_symbols(krate.into()))
|
||||
.collect();
|
||||
crates
|
||||
.par_iter()
|
||||
.for_each_with(db.clone(), |snap, &krate| _ = crate_symbols(snap, krate.into()));
|
||||
let indices: Vec<_> =
|
||||
crates.into_iter().map(|krate| crate_symbols(db, krate.into())).collect();
|
||||
indices.iter().flat_map(|indices| indices.iter().cloned()).collect()
|
||||
};
|
||||
|
||||
@ -221,6 +189,62 @@ pub struct SymbolIndex {
|
||||
map: fst::Map<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl SymbolIndex {
|
||||
/// The symbol index for a given source root within library_roots.
|
||||
pub fn library_symbols(db: &dyn HirDatabase, source_root_id: SourceRootId) -> &SymbolIndex {
|
||||
// FIXME:
|
||||
#[salsa::interned]
|
||||
struct InternedSourceRootId {
|
||||
id: SourceRootId,
|
||||
}
|
||||
#[salsa::tracked(returns(ref))]
|
||||
fn library_symbols(
|
||||
db: &dyn HirDatabase,
|
||||
source_root_id: InternedSourceRootId<'_>,
|
||||
) -> SymbolIndex {
|
||||
let _p = tracing::info_span!("library_symbols").entered();
|
||||
|
||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||
hir::attach_db(db, || {
|
||||
let mut symbol_collector = SymbolCollector::new(db);
|
||||
|
||||
db.source_root_crates(source_root_id.id(db))
|
||||
.iter()
|
||||
.flat_map(|&krate| Crate::from(krate).modules(db))
|
||||
// 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
|
||||
// the module or crate indices for those in salsa unless we need to.
|
||||
.for_each(|module| symbol_collector.collect(module));
|
||||
|
||||
SymbolIndex::new(symbol_collector.finish())
|
||||
})
|
||||
}
|
||||
library_symbols(db, InternedSourceRootId::new(db, source_root_id))
|
||||
}
|
||||
|
||||
/// The symbol index for a given module. These modules should only be in source roots that
|
||||
/// are inside local_roots.
|
||||
pub fn module_symbols(db: &dyn HirDatabase, module: Module) -> &SymbolIndex {
|
||||
// FIXME:
|
||||
#[salsa::interned]
|
||||
struct InternedModuleId {
|
||||
id: hir::ModuleId,
|
||||
}
|
||||
|
||||
#[salsa::tracked(returns(ref))]
|
||||
fn module_symbols(db: &dyn HirDatabase, module: InternedModuleId<'_>) -> SymbolIndex {
|
||||
let _p = tracing::info_span!("module_symbols").entered();
|
||||
|
||||
// We call this without attaching because this runs in parallel, so we need to attach here.
|
||||
hir::attach_db(db, || {
|
||||
SymbolIndex::new(SymbolCollector::new_module(db, module.id(db).into()))
|
||||
})
|
||||
}
|
||||
|
||||
module_symbols(db, InternedModuleId::new(db, hir::ModuleId::from(module)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SymbolIndex {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SymbolIndex").field("n_symbols", &self.symbols.len()).finish()
|
||||
@ -309,7 +333,7 @@ impl SymbolIndex {
|
||||
impl Query {
|
||||
pub(crate) fn search<'sym, T>(
|
||||
self,
|
||||
indices: &'sym [Arc<SymbolIndex>],
|
||||
indices: &'sym [&SymbolIndex],
|
||||
cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>,
|
||||
) -> Option<T> {
|
||||
let _p = tracing::info_span!("symbol_index::Query::search").entered();
|
||||
@ -344,7 +368,7 @@ impl Query {
|
||||
|
||||
fn search_maps<'sym, T>(
|
||||
&self,
|
||||
indices: &'sym [Arc<SymbolIndex>],
|
||||
indices: &'sym [&SymbolIndex],
|
||||
mut stream: fst::map::Union<'_>,
|
||||
mut cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>,
|
||||
) -> Option<T> {
|
||||
@ -397,7 +421,7 @@ impl Query {
|
||||
mod tests {
|
||||
|
||||
use expect_test::expect_file;
|
||||
use salsa::Durability;
|
||||
use salsa::Setter;
|
||||
use test_fixture::{WORKSPACE, WithFixture};
|
||||
|
||||
use super::*;
|
||||
@ -535,7 +559,7 @@ pub struct Foo;
|
||||
|
||||
let mut local_roots = FxHashSet::default();
|
||||
local_roots.insert(WORKSPACE);
|
||||
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
|
||||
LocalRoots::get(&db).set_roots(&mut db).to(local_roots);
|
||||
|
||||
let mut query = Query::new("Foo".to_owned());
|
||||
let mut symbols = world_symbols(&db, query.clone());
|
||||
|
||||
@ -80,7 +80,7 @@ pub use crate::{errors::SsrError, from_comment::ssr_from_comment, matching::Matc
|
||||
|
||||
use crate::{errors::bail, matching::MatchFailureReason};
|
||||
use hir::{FileRange, Semantics};
|
||||
use ide_db::symbol_index::SymbolsDatabase;
|
||||
use ide_db::symbol_index::LocalRoots;
|
||||
use ide_db::text_edit::TextEdit;
|
||||
use ide_db::{EditionedFileId, FileId, FxHashMap, RootDatabase, base_db::SourceDatabase};
|
||||
use resolving::ResolvedRule;
|
||||
@ -138,8 +138,8 @@ impl<'db> MatchFinder<'db> {
|
||||
|
||||
/// Constructs an instance using the start of the first file in `db` as the lookup context.
|
||||
pub fn at_first_file(db: &'db ide_db::RootDatabase) -> Result<MatchFinder<'db>, SsrError> {
|
||||
if let Some(first_file_id) = db
|
||||
.local_roots()
|
||||
if let Some(first_file_id) = LocalRoots::get(db)
|
||||
.roots(db)
|
||||
.iter()
|
||||
.next()
|
||||
.and_then(|root| db.source_root(*root).source_root(db).iter().next())
|
||||
|
||||
@ -9,6 +9,7 @@ use ide_db::{
|
||||
EditionedFileId, FileId, FxHashSet,
|
||||
defs::Definition,
|
||||
search::{SearchScope, UsageSearchResult},
|
||||
symbol_index::LocalRoots,
|
||||
};
|
||||
use syntax::{AstNode, SyntaxKind, SyntaxNode, ast};
|
||||
|
||||
@ -156,8 +157,7 @@ impl<'db> MatchFinder<'db> {
|
||||
if self.restrict_ranges.is_empty() {
|
||||
// Unrestricted search.
|
||||
use ide_db::base_db::SourceDatabase;
|
||||
use ide_db::symbol_index::SymbolsDatabase;
|
||||
for &root in self.sema.db.local_roots().iter() {
|
||||
for &root in LocalRoots::get(self.sema.db).roots(self.sema.db).iter() {
|
||||
let sr = self.sema.db.source_root(root).source_root(self.sema.db);
|
||||
for file_id in sr.iter() {
|
||||
callback(file_id);
|
||||
|
||||
@ -2,10 +2,10 @@ use expect_test::{Expect, expect};
|
||||
use hir::{FilePosition, FileRange};
|
||||
use ide_db::{
|
||||
EditionedFileId, FxHashSet,
|
||||
base_db::{SourceDatabase, salsa::Durability},
|
||||
base_db::{SourceDatabase, salsa::Setter},
|
||||
symbol_index::LocalRoots,
|
||||
};
|
||||
use test_utils::RangeOrOffset;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{MatchFinder, SsrRule};
|
||||
|
||||
@ -66,7 +66,6 @@ fn parser_undefined_placeholder_in_replacement() {
|
||||
/// `code` may optionally contain a cursor marker `$0`. If it doesn't, then the position will be
|
||||
/// the start of the file. If there's a second cursor marker, then we'll return a single range.
|
||||
pub(crate) fn single_file(code: &str) -> (ide_db::RootDatabase, FilePosition, Vec<FileRange>) {
|
||||
use ide_db::symbol_index::SymbolsDatabase;
|
||||
use test_fixture::{WORKSPACE, WithFixture};
|
||||
let (mut db, file_id, range_or_offset) = if code.contains(test_utils::CURSOR_MARKER) {
|
||||
ide_db::RootDatabase::with_range_or_offset(code)
|
||||
@ -88,7 +87,7 @@ pub(crate) fn single_file(code: &str) -> (ide_db::RootDatabase, FilePosition, Ve
|
||||
}
|
||||
let mut local_roots = FxHashSet::default();
|
||||
local_roots.insert(WORKSPACE);
|
||||
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
|
||||
LocalRoots::get(&db).set_roots(&mut db).to(local_roots);
|
||||
(db, position, selections)
|
||||
}
|
||||
|
||||
|
||||
@ -59,11 +59,9 @@ mod tests {
|
||||
use expect_test::expect;
|
||||
use ide_assists::{Assist, AssistResolveStrategy};
|
||||
use ide_db::{
|
||||
FileRange, FxHashSet, RootDatabase, base_db::salsa::Durability,
|
||||
symbol_index::SymbolsDatabase,
|
||||
FileRange, FxHashSet, RootDatabase, base_db::salsa::Setter as _, symbol_index::LocalRoots,
|
||||
};
|
||||
use test_fixture::WithFixture;
|
||||
use triomphe::Arc;
|
||||
|
||||
use super::ssr_assists;
|
||||
|
||||
@ -74,7 +72,7 @@ mod tests {
|
||||
let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
|
||||
let mut local_roots = FxHashSet::default();
|
||||
local_roots.insert(test_fixture::WORKSPACE);
|
||||
db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
|
||||
LocalRoots::get(&db).set_roots(&mut db).to(local_roots);
|
||||
ssr_assists(
|
||||
&db,
|
||||
&resolve,
|
||||
|
||||
@ -50,7 +50,6 @@ impl flags::Search {
|
||||
/// for much else.
|
||||
pub fn run(self) -> anyhow::Result<()> {
|
||||
use ide_db::base_db::SourceDatabase;
|
||||
use ide_db::symbol_index::SymbolsDatabase;
|
||||
let cargo_config =
|
||||
CargoConfig { all_targets: true, set_test: true, ..CargoConfig::default() };
|
||||
let load_cargo_config = LoadCargoConfig {
|
||||
@ -69,7 +68,7 @@ impl flags::Search {
|
||||
match_finder.add_search_pattern(pattern)?;
|
||||
}
|
||||
if let Some(debug_snippet) = &self.debug {
|
||||
for &root in db.local_roots().iter() {
|
||||
for &root in ide_db::symbol_index::LocalRoots::get(db).roots(db).iter() {
|
||||
let sr = db.source_root(root).source_root(db);
|
||||
for file_id in sr.iter() {
|
||||
for debug_info in match_finder.debug_where_text_equal(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user