internal: Move library and local root inputs to base-db

This commit is contained in:
Lukas Wirth 2025-12-27 11:00:58 +01:00
parent f9e29cfb70
commit 1c67944f99
17 changed files with 101 additions and 68 deletions

View File

@ -3,11 +3,14 @@
use std::fmt;
use salsa::Durability;
use rustc_hash::FxHashSet;
use salsa::{Durability, Setter as _};
use triomphe::Arc;
use vfs::FileId;
use crate::{CrateGraphBuilder, CratesIdMap, RootQueryDb, SourceRoot, SourceRootId};
use crate::{
CrateGraphBuilder, CratesIdMap, LibraryRoots, LocalRoots, RootQueryDb, SourceRoot, SourceRootId,
};
/// Encapsulate a bunch of raw `.set` calls on the database.
#[derive(Default)]
@ -49,8 +52,15 @@ impl FileChange {
pub fn apply(self, db: &mut dyn RootQueryDb) -> Option<CratesIdMap> {
let _p = tracing::info_span!("FileChange::apply").entered();
if let Some(roots) = self.roots {
let mut local_roots = FxHashSet::default();
let mut library_roots = FxHashSet::default();
for (idx, root) in roots.into_iter().enumerate() {
let root_id = SourceRootId(idx as u32);
if root.is_library {
library_roots.insert(root_id);
} else {
local_roots.insert(root_id);
}
let durability = source_root_durability(&root);
for file_id in root.iter() {
db.set_file_source_root_with_durability(file_id, root_id, durability);
@ -58,6 +68,8 @@ impl FileChange {
db.set_source_root_with_durability(root_id, Arc::new(root), durability);
}
LocalRoots::get(db).set_roots(db).to(local_roots);
LibraryRoots::get(db).set_roots(db).to(library_roots);
}
for (file_id, text) in self.files_changed {

View File

@ -33,7 +33,7 @@ pub use crate::{
};
use dashmap::{DashMap, mapref::entry::Entry};
pub use query_group::{self};
use rustc_hash::FxHasher;
use rustc_hash::{FxHashSet, FxHasher};
use salsa::{Durability, Setter};
pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
use syntax::{Parse, SyntaxError, ast};
@ -203,6 +203,22 @@ impl Files {
}
}
/// The set of roots for crates.io libraries.
/// Files in libraries are assumed to never change.
#[salsa::input(singleton, debug)]
pub struct LibraryRoots {
#[returns(ref)]
pub roots: FxHashSet<SourceRootId>,
}
/// The set of "local" (that is, from the current workspace) roots.
/// Files in local roots are assumed to change frequently.
#[salsa::input(singleton, debug)]
pub struct LocalRoots {
#[returns(ref)]
pub roots: FxHashSet<SourceRootId>,
}
#[salsa_macros::input(debug)]
pub struct FileText {
#[returns(ref)]

View File

@ -190,13 +190,13 @@ fn f() {
"#,
expect![[r#"
ModuleIdLt {
[salsa id]: Id(3003),
[salsa id]: Id(3803),
krate: Crate(
Id(1c00),
Id(2400),
),
block: Some(
BlockId(
3c01,
4401,
),
),
}"#]],

View File

@ -35,9 +35,9 @@ macro_rules! f {
};
}
struct#0:MacroRules[BE8F, 0]@58..64#15360# MyTraitMap2#0:MacroCall[BE8F, 0]@31..42#ROOT2024# {#0:MacroRules[BE8F, 0]@72..73#15360#
map#0:MacroRules[BE8F, 0]@86..89#15360#:#0:MacroRules[BE8F, 0]@89..90#15360# #0:MacroRules[BE8F, 0]@89..90#15360#::#0:MacroRules[BE8F, 0]@91..93#15360#std#0:MacroRules[BE8F, 0]@93..96#15360#::#0:MacroRules[BE8F, 0]@96..98#15360#collections#0:MacroRules[BE8F, 0]@98..109#15360#::#0:MacroRules[BE8F, 0]@109..111#15360#HashSet#0:MacroRules[BE8F, 0]@111..118#15360#<#0:MacroRules[BE8F, 0]@118..119#15360#(#0:MacroRules[BE8F, 0]@119..120#15360#)#0:MacroRules[BE8F, 0]@120..121#15360#>#0:MacroRules[BE8F, 0]@121..122#15360#,#0:MacroRules[BE8F, 0]@122..123#15360#
}#0:MacroRules[BE8F, 0]@132..133#15360#
struct#0:MacroRules[BE8F, 0]@58..64#17408# MyTraitMap2#0:MacroCall[BE8F, 0]@31..42#ROOT2024# {#0:MacroRules[BE8F, 0]@72..73#17408#
map#0:MacroRules[BE8F, 0]@86..89#17408#:#0:MacroRules[BE8F, 0]@89..90#17408# #0:MacroRules[BE8F, 0]@89..90#17408#::#0:MacroRules[BE8F, 0]@91..93#17408#std#0:MacroRules[BE8F, 0]@93..96#17408#::#0:MacroRules[BE8F, 0]@96..98#17408#collections#0:MacroRules[BE8F, 0]@98..109#17408#::#0:MacroRules[BE8F, 0]@109..111#17408#HashSet#0:MacroRules[BE8F, 0]@111..118#17408#<#0:MacroRules[BE8F, 0]@118..119#17408#(#0:MacroRules[BE8F, 0]@119..120#17408#)#0:MacroRules[BE8F, 0]@120..121#17408#>#0:MacroRules[BE8F, 0]@121..122#17408#,#0:MacroRules[BE8F, 0]@122..123#17408#
}#0:MacroRules[BE8F, 0]@132..133#17408#
"#]],
);
}
@ -197,7 +197,7 @@ macro_rules! mk_struct {
#[macro_use]
mod foo;
struct#1:MacroRules[DB0C, 0]@59..65#15360# Foo#0:MacroCall[DB0C, 0]@32..35#ROOT2024#(#1:MacroRules[DB0C, 0]@70..71#15360#u32#0:MacroCall[DB0C, 0]@41..44#ROOT2024#)#1:MacroRules[DB0C, 0]@74..75#15360#;#1:MacroRules[DB0C, 0]@75..76#15360#
struct#1:MacroRules[DB0C, 0]@59..65#17408# Foo#0:MacroCall[DB0C, 0]@32..35#ROOT2024#(#1:MacroRules[DB0C, 0]@70..71#17408#u32#0:MacroCall[DB0C, 0]@41..44#ROOT2024#)#1:MacroRules[DB0C, 0]@74..75#17408#;#1:MacroRules[DB0C, 0]@75..76#17408#
"#]],
);
}
@ -423,10 +423,10 @@ m! { foo, bar }
macro_rules! m {
($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
}
impl#\15360# Bar#\15360# {#\15360#
fn#\15360# foo#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360#
fn#\15360# bar#\ROOT2024#(#\15360#)#\15360# {#\15360#}#\15360#
}#\15360#
impl#\17408# Bar#\17408# {#\17408#
fn#\17408# foo#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408#
fn#\17408# bar#\ROOT2024#(#\17408#)#\17408# {#\17408#}#\17408#
}#\17408#
"#]],
);
}

View File

@ -502,6 +502,7 @@ impl DefMap {
}
impl DefMap {
/// Returns all modules in the crate that are associated with the given file.
pub fn modules_for_file<'a>(
&'a self,
db: &'a dyn DefDatabase,
@ -509,16 +510,33 @@ impl DefMap {
) -> impl Iterator<Item = ModuleId> + 'a {
self.modules
.iter()
.filter(move |(_id, data)| {
.filter(move |(_, data)| {
data.origin.file_id().map(|file_id| file_id.file_id(db)) == Some(file_id)
})
.map(|(id, _data)| id)
.map(|(id, _)| id)
}
pub fn modules(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
self.modules.iter()
}
/// Returns all inline modules (mod name { ... }) in the crate that are associated with the given macro expansion.
pub fn inline_modules_for_macro_file(
&self,
file_id: MacroCallId,
) -> impl Iterator<Item = ModuleId> + '_ {
self.modules
.iter()
.filter(move |(_, data)| {
matches!(
data.origin,
ModuleOrigin::Inline { definition_tree_id, .. }
if definition_tree_id.file_id().macro_file() == Some(file_id)
)
})
.map(|(id, _)| id)
}
pub fn derive_helpers_in_scope(
&self,
id: AstId<ast::Adt>,

View File

@ -49,6 +49,12 @@ impl Default for TestDB {
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
// This needs to be here otherwise `CrateGraphBuilder` panics.
this.set_all_crates(Arc::new(Box::new([])));
_ = base_db::LibraryRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&this);
_ = base_db::LocalRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&this);
CrateGraphBuilder::default().set_in_db(&mut this);
this
}

View File

@ -46,6 +46,12 @@ impl Default for TestDB {
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
// This needs to be here otherwise `CrateGraphBuilder` panics.
this.set_all_crates(Arc::new(Box::new([])));
_ = base_db::LibraryRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&this);
_ = base_db::LocalRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&this);
CrateGraphBuilder::default().set_in_db(&mut this);
this
}

View File

@ -836,7 +836,7 @@ impl<'db> SemanticsImpl<'db> {
// FIXME: Type the return type
/// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
/// absolute file range (post-expansion)
/// of the part in the format string, the corresponding string token and the resolution if it
/// of the part in the format string (post-expansion), the corresponding string token and the resolution if it
/// exists.
// FIXME: Remove this in favor of `check_for_format_args_template_with_file`
pub fn check_for_format_args_template(

View File

@ -1,14 +1,9 @@
//! Applies changes to the IDE state transactionally.
use base_db::SourceRootId;
use profile::Bytes;
use rustc_hash::FxHashSet;
use salsa::{Database as _, Durability, Setter as _};
use salsa::{Database as _, Durability};
use crate::{
ChangeWithProcMacros, RootDatabase,
symbol_index::{LibraryRoots, LocalRoots},
};
use crate::{ChangeWithProcMacros, RootDatabase};
impl RootDatabase {
pub fn request_cancellation(&mut self) {
@ -20,20 +15,6 @@ impl RootDatabase {
let _p = tracing::info_span!("RootDatabase::apply_change").entered();
self.request_cancellation();
tracing::trace!("apply_change {:?}", change);
if let Some(roots) = &change.source_change.roots {
let mut local_roots = FxHashSet::default();
let mut library_roots = FxHashSet::default();
for (idx, root) in roots.iter().enumerate() {
let root_id = SourceRootId(idx as u32);
if root.is_library {
library_roots.insert(root_id);
} else {
local_roots.insert(root_id);
}
}
LocalRoots::get(self).set_roots(self).to(local_roots);
LibraryRoots::get(self).set_roots(self).to(library_roots);
}
change.apply(self);
}

View File

@ -75,7 +75,7 @@ pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
pub use ::line_index;
/// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
pub use base_db::{self, FxIndexMap, FxIndexSet};
pub use base_db::{self, FxIndexMap, FxIndexSet, LibraryRoots, LocalRoots};
pub use span::{self, FileId};
pub type FilePosition = FilePositionWrapper<FileId>;
@ -200,10 +200,10 @@ impl RootDatabase {
db.set_all_crates(Arc::new(Box::new([])));
CrateGraphBuilder::default().set_in_db(&mut db);
db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM);
_ = crate::symbol_index::LibraryRoots::builder(Default::default())
_ = base_db::LibraryRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&db);
_ = crate::symbol_index::LocalRoots::builder(Default::default())
_ = base_db::LocalRoots::builder(Default::default())
.durability(Durability::MEDIUM)
.new(&db);
db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH);

View File

@ -27,7 +27,7 @@ use std::{
ops::ControlFlow,
};
use base_db::{RootQueryDb, SourceRootId};
use base_db::{LibraryRoots, LocalRoots, RootQueryDb, SourceRootId};
use fst::{Automaton, Streamer, raw::IndexedValue};
use hir::{
Crate, Module,
@ -36,7 +36,6 @@ use hir::{
symbols::{FileSymbol, SymbolCollector},
};
use rayon::prelude::*;
use rustc_hash::FxHashSet;
use salsa::Update;
use crate::RootDatabase;
@ -102,22 +101,6 @@ impl Query {
}
}
/// The set of roots for crates.io libraries.
/// Files in libraries are assumed to never change.
#[salsa::input(singleton, debug)]
pub struct LibraryRoots {
#[returns(ref)]
pub roots: FxHashSet<SourceRootId>,
}
/// The set of "local" (that is, from the current workspace) roots.
/// Files in local roots are assumed to change frequently.
#[salsa::input(singleton, debug)]
pub struct LocalRoots {
#[returns(ref)]
pub roots: FxHashSet<SourceRootId>,
}
/// The symbol indices of modules that make up a given crate.
pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex<'_>]> {
let _p = tracing::info_span!("crate_symbols").entered();
@ -443,6 +426,7 @@ impl Query {
mod tests {
use expect_test::expect_file;
use rustc_hash::FxHashSet;
use salsa::Setter;
use test_fixture::{WORKSPACE, WithFixture};

View File

@ -85,7 +85,7 @@ pub use crate::{errors::SsrError, from_comment::ssr_from_comment, matching::Matc
use crate::{errors::bail, matching::MatchFailureReason};
use hir::{FileRange, Semantics};
use ide_db::symbol_index::LocalRoots;
use ide_db::LocalRoots;
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, FileId, FxHashMap, RootDatabase, base_db::SourceDatabase};
use resolving::ResolvedRule;

View File

@ -6,10 +6,9 @@ use crate::{
};
use hir::FileRange;
use ide_db::{
FileId, FxHashSet,
FileId, FxHashSet, LocalRoots,
defs::Definition,
search::{SearchScope, UsageSearchResult},
symbol_index::LocalRoots,
};
use syntax::{AstNode, SyntaxKind, SyntaxNode, ast};

View File

@ -1,9 +1,8 @@
use expect_test::{Expect, expect};
use hir::{FilePosition, FileRange};
use ide_db::{
EditionedFileId, FxHashSet,
EditionedFileId, FxHashSet, LocalRoots,
base_db::{SourceDatabase, salsa::Setter},
symbol_index::LocalRoots,
};
use test_utils::RangeOrOffset;

View File

@ -58,9 +58,7 @@ pub(crate) fn ssr_assists(
mod tests {
use expect_test::expect;
use ide_assists::{Assist, AssistResolveStrategy};
use ide_db::{
FileRange, FxHashSet, RootDatabase, base_db::salsa::Setter as _, symbol_index::LocalRoots,
};
use ide_db::{FileRange, FxHashSet, LocalRoots, RootDatabase, base_db::salsa::Setter as _};
use test_fixture::WithFixture;
use super::ssr_assists;

View File

@ -68,7 +68,7 @@ impl flags::Search {
match_finder.add_search_pattern(pattern)?;
}
if let Some(debug_snippet) = &self.debug {
for &root in ide_db::symbol_index::LocalRoots::get(db).roots(db).iter() {
for &root in ide_db::LocalRoots::get(db).roots(db).iter() {
let sr = db.source_root(root).source_root(db);
for file_id in sr.iter() {
for debug_info in match_finder.debug_where_text_equal(

View File

@ -76,6 +76,20 @@ impl<T, U, V> TupleExt for (T, U, V) {
}
}
impl<T> TupleExt for &T
where
T: TupleExt + Copy,
{
type Head = T::Head;
type Tail = T::Tail;
fn head(self) -> Self::Head {
(*self).head()
}
fn tail(self) -> Self::Tail {
(*self).tail()
}
}
pub fn to_lower_snake_case(s: &str) -> String {
to_snake_case(s, char::to_lowercase)
}