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.rs77
1 files changed, 63 insertions, 14 deletions
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index 1d73ba804a..f7f4e024ef 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,
}
@@ -60,7 +63,7 @@ impl Files {
match self.files.get(&file_id) {
Some(text) => *text,
None => {
- panic!("Unable to fetch file text for `vfs::FileId`: {:?}; this is a bug", file_id)
+ panic!("Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug")
}
}
}
@@ -101,8 +104,7 @@ impl Files {
let source_root = match self.source_roots.get(&source_root_id) {
Some(source_root) => source_root,
None => panic!(
- "Unable to fetch `SourceRootInput` with `SourceRootId` ({:?}); this is a bug",
- source_root_id
+ "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug"
),
};
@@ -132,8 +134,7 @@ impl Files {
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` ({:?}); this is a bug",
- id
+ "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug",
),
};
*file_source_root
@@ -163,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,
}
@@ -198,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>,
}
@@ -276,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;
@@ -355,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 {
@@ -384,3 +385,51 @@ 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]
+pub struct DbPanicContext {
+ // prevent arbitrary construction
+ _priv: (),
+}
+
+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| {
+ DbPanicContext::with_ctx(|ctx| {
+ if !ctx.is_empty() {
+ eprintln!("Panic context:");
+ for frame in ctx.iter() {
+ eprintln!("> {frame}\n");
+ }
+ }
+ });
+ if let Some(backtrace) = salsa::Backtrace::capture() {
+ eprintln!("{backtrace}");
+ }
+ default_hook(panic_info);
+ }));
+ }
+
+ static SET_HOOK: Once = Once::new();
+ SET_HOOK.call_once(set_hook);
+
+ Self::with_ctx(|ctx| ctx.push(frame));
+ DbPanicContext { _priv: () }
+ }
+
+ 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()));
+ }
+}