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 | 108 |
1 files changed, 49 insertions, 59 deletions
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 5baf4ce6f9..e438505c07 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -36,7 +36,6 @@ pub use query_group; use rustc_hash::{FxHashSet, FxHasher}; use salsa::{Durability, Setter}; pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; -use syntax::{Parse, SyntaxError, ast}; use triomphe::Arc; pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}; @@ -236,36 +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::Database { - /// Parses the file into the syntax tree. - #[salsa::invoke(parse)] - #[salsa::lru(128)] - fn parse(&self, file_id: EditionedFileId) -> Parse<ast::SourceFile>; - - /// Returns the set of errors obtained from parsing the file including validation errors. - #[salsa::transparent] - fn parse_errors(&self, file_id: EditionedFileId) -> Option<&[SyntaxError]>; - - #[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. @@ -353,46 +322,67 @@ 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 parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFile> { - let _p = tracing::info_span!("parse", ?file_id).entered(); - let (file_id, edition) = file_id.unpack(db.as_dyn_database()); - let text = db.file_text(file_id).text(db); - ast::SourceFile::parse(text, edition) +#[salsa::input(singleton, debug)] +struct AllCrates { + crates: std::sync::Arc<[Crate]>, } -fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> { - #[salsa_macros::tracked(returns(ref))] - fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<Box<[SyntaxError]>> { - let errors = db.parse(file_id).errors(); - match &*errors { - [] => None, - [..] => Some(errors.into()), - } - } - parse_errors(db, file_id).as_ref().map(|it| &**it) +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()); } -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() +/// 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)) +} + +// 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] |