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.rs88
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]