Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/base-db/src/lib.rs')
| -rw-r--r-- | crates/base-db/src/lib.rs | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index b1cb1b3202..26eef9ac0d 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -235,27 +235,6 @@ pub struct SourceRootInput { pub source_root: Arc<SourceRoot>, } -/// Database which stores all significant input facts: source code and project -/// model. Everything else in rust-analyzer is derived from these queries. -#[query_group::query_group] -pub trait RootQueryDb: SourceDatabase { - #[salsa::transparent] - fn toolchain_channel(&self, krate: Crate) -> Option<ReleaseChannel>; - - /// Crates whose root file is in `id`. - #[salsa::invoke_interned(source_root_crates)] - fn source_root_crates(&self, id: SourceRootId) -> Arc<[Crate]>; - - #[salsa::transparent] - fn relevant_crates(&self, file_id: FileId) -> Arc<[Crate]>; - - /// Returns the crates in topological order. - /// - /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. - #[salsa::input] - fn all_crates(&self) -> Arc<Box<[Crate]>>; -} - #[salsa_macros::db] pub trait SourceDatabase: salsa::Database { /// Text of the file. @@ -343,27 +322,68 @@ impl CrateWorkspaceData { } } -fn toolchain_channel(db: &dyn RootQueryDb, krate: Crate) -> Option<ReleaseChannel> { +pub fn toolchain_channel(db: &dyn salsa::Database, krate: Crate) -> Option<ReleaseChannel> { krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre)) } -fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[Crate]> { - let crates = db.all_crates(); - crates - .iter() - .copied() - .filter(|&krate| { - let root_file = krate.data(db).root_file_id; - db.file_source_root(root_file).source_root_id(db) == id - }) - .collect() +#[salsa::input(singleton, debug)] +struct AllCrates { + crates: std::sync::Arc<[Crate]>, +} + +pub fn set_all_crates_with_durability( + db: &mut dyn salsa::Database, + crates: impl IntoIterator<Item = Crate>, + durability: Durability, +) { + AllCrates::try_get(db) + .unwrap_or_else(|| AllCrates::new(db, std::sync::Arc::default())) + .set_crates(db) + .with_durability(durability) + .to(crates.into_iter().collect()); +} + +/// Returns the crates in topological order. +/// +/// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. +pub fn all_crates(db: &dyn salsa::Database) -> std::sync::Arc<[Crate]> { + AllCrates::try_get(db) + .map_or(std::sync::Arc::default(), |all_crates| all_crates.crates(db).into()) +} + +// FIXME: VFS rewrite should allow us to get rid of this wrapper +#[doc(hidden)] +#[salsa::interned] +pub struct InternedSourceRootId { + pub id: SourceRootId, +} + +/// Crates whose root file is in `id`. +pub fn source_root_crates(db: &dyn SourceDatabase, id: SourceRootId) -> &[Crate] { + #[salsa::tracked(returns(deref))] + pub fn source_root_crates<'db>( + db: &'db dyn SourceDatabase, + id: InternedSourceRootId<'db>, + ) -> Box<[Crate]> { + let crates = AllCrates::get(db).crates(db); + let id = id.id(db); + crates + .iter() + .copied() + .filter(|&krate| { + let root_file = krate.data(db).root_file_id; + db.file_source_root(root_file).source_root_id(db) == id + }) + .collect() + } + source_root_crates(db, InternedSourceRootId::new(db, id)) } -fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> { +pub fn relevant_crates(db: &dyn SourceDatabase, file_id: FileId) -> &[Crate] { let _p = tracing::info_span!("relevant_crates").entered(); let source_root = db.file_source_root(file_id); - db.source_root_crates(source_root.source_root_id(db)) + source_root_crates(db, source_root.source_root_id(db)) } #[must_use] |