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.rs94
1 files changed, 76 insertions, 18 deletions
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index 7f7a712577..a67fbf75c0 100644
--- a/crates/base-db/src/lib.rs
+++ b/crates/base-db/src/lib.rs
@@ -1,9 +1,13 @@
//! base_db defines basic database traits. The concrete DB is defined by ide.
+
+pub use salsa;
+pub use salsa_macros;
+
// FIXME: Rename this crate, base db is non descriptive
mod change;
mod input;
-use std::hash::BuildHasherDefault;
+use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once};
pub use crate::{
change::FileChange,
@@ -17,7 +21,6 @@ pub use crate::{
use dashmap::{DashMap, mapref::entry::Entry};
pub use query_group::{self};
use rustc_hash::{FxHashSet, FxHasher};
-pub use salsa::{self};
use salsa::{Durability, Setter};
pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
use span::Edition;
@@ -28,7 +31,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}
#[macro_export]
macro_rules! impl_intern_key {
($id:ident, $loc:ident) => {
- #[salsa::interned(no_lifetime)]
+ #[salsa_macros::interned(no_lifetime)]
pub struct $id {
pub loc: $loc,
}
@@ -57,7 +60,12 @@ pub struct Files {
impl Files {
pub fn file_text(&self, file_id: vfs::FileId) -> FileText {
- *self.files.get(&file_id).expect("Unable to fetch file; this is a bug")
+ match self.files.get(&file_id) {
+ Some(text) => *text,
+ None => {
+ panic!("Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug")
+ }
+ }
}
pub fn set_file_text(&self, db: &mut dyn SourceDatabase, file_id: vfs::FileId, text: &str) {
@@ -93,10 +101,12 @@ impl Files {
/// Source root of the file.
pub fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput {
- let source_root = self
- .source_roots
- .get(&source_root_id)
- .expect("Unable to fetch source root id; this is a bug");
+ let source_root = match self.source_roots.get(&source_root_id) {
+ Some(source_root) => source_root,
+ None => panic!(
+ "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug"
+ ),
+ };
*source_root
}
@@ -121,10 +131,12 @@ impl Files {
}
pub fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput {
- let file_source_root = self
- .file_source_roots
- .get(&id)
- .expect("Unable to fetch FileSourceRootInput; this is a bug");
+ let file_source_root = match self.file_source_roots.get(&id) {
+ Some(file_source_root) => file_source_root,
+ None => panic!(
+ "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug",
+ ),
+ };
*file_source_root
}
@@ -152,7 +164,7 @@ impl Files {
}
}
-#[salsa::interned(no_lifetime, debug, constructor=from_span)]
+#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
pub struct EditionedFileId {
pub editioned_file_id: span::EditionedFileId,
}
@@ -187,18 +199,18 @@ impl EditionedFileId {
}
}
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
pub struct FileText {
pub text: Arc<str>,
pub file_id: vfs::FileId,
}
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
pub struct FileSourceRootInput {
pub source_root_id: SourceRootId,
}
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
pub struct SourceRootInput {
pub source_root: Arc<SourceRoot>,
}
@@ -265,7 +277,7 @@ pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet<Cr
deps
}
-#[salsa::db]
+#[salsa_macros::db]
pub trait SourceDatabase: salsa::Database {
/// Text of the file.
fn file_text(&self, file_id: vfs::FileId) -> FileText;
@@ -344,7 +356,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFil
}
fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> {
- #[salsa::tracked(return_ref)]
+ #[salsa_macros::tracked(return_ref)]
fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<Box<[SyntaxError]>> {
let errors = db.parse(file_id).errors();
match &*errors {
@@ -373,3 +385,49 @@ fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> {
let source_root = db.file_source_root(file_id);
db.source_root_crates(source_root.source_root_id(db))
}
+
+#[must_use]
+#[non_exhaustive]
+pub struct DbPanicContext;
+
+impl Drop for DbPanicContext {
+ fn drop(&mut self) {
+ Self::with_ctx(|ctx| assert!(ctx.pop().is_some()));
+ }
+}
+
+impl DbPanicContext {
+ pub fn enter(frame: String) -> DbPanicContext {
+ #[expect(clippy::print_stderr, reason = "already panicking anyway")]
+ fn set_hook() {
+ let default_hook = panic::take_hook();
+ panic::set_hook(Box::new(move |panic_info| {
+ default_hook(panic_info);
+ if let Some(backtrace) = salsa::Backtrace::capture() {
+ eprintln!("{backtrace:#}");
+ }
+ DbPanicContext::with_ctx(|ctx| {
+ if !ctx.is_empty() {
+ eprintln!("additional context:");
+ for (idx, frame) in ctx.iter().enumerate() {
+ eprintln!("{idx:>4}: {frame}\n");
+ }
+ }
+ });
+ }));
+ }
+
+ static SET_HOOK: Once = Once::new();
+ SET_HOOK.call_once(set_hook);
+
+ Self::with_ctx(|ctx| ctx.push(frame));
+ DbPanicContext
+ }
+
+ fn with_ctx(f: impl FnOnce(&mut Vec<String>)) {
+ thread_local! {
+ static CTX: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
+ }
+ CTX.with(|ctx| f(&mut ctx.borrow_mut()));
+ }
+}