Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/base-db/src/input.rs')
| -rw-r--r-- | crates/base-db/src/input.rs | 86 |
1 files changed, 59 insertions, 27 deletions
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index cac74778a2..5149d2d005 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -460,6 +460,61 @@ pub struct Crate { pub env: Env, } +impl Crate { + /// Returns an iterator over all transitive dependencies of the given crate, + /// including the crate itself. + /// + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. + pub fn transitive_deps(self, db: &dyn salsa::Database) -> Box<[Crate]> { + // There is a bit of duplication here and in `CrateGraphBuilder` in the same method, but it's not terrible + // and removing that is a bit difficult. + let mut worklist = vec![self]; + let mut deps_seen = FxHashSet::default(); + let mut deps = Vec::new(); + + while let Some(krate) = worklist.pop() { + if !deps_seen.insert(krate) { + continue; + } + deps.push(krate); + + worklist.extend(krate.data(db).dependencies.iter().map(|dep| dep.crate_id)); + } + deps.into_boxed_slice() + } + + /// Returns all transitive reverse dependencies of the given crate, + /// including the crate itself. + /// + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. + pub fn transitive_rev_deps(self, db: &dyn RootQueryDb) -> Box<[Crate]> { + let mut worklist = vec![self]; + let mut rev_deps = FxHashSet::default(); + rev_deps.insert(self); + + let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); + db.all_crates().iter().for_each(|&krate| { + krate + .data(db) + .dependencies + .iter() + .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate)) + }); + + while let Some(krate) = worklist.pop() { + if let Some(crate_rev_deps) = inverted_graph.get(&krate) { + crate_rev_deps + .iter() + .copied() + .filter(|&rev_dep| rev_deps.insert(rev_dep)) + .for_each(|rev_dep| worklist.push(rev_dep)); + } + } + + rev_deps.into_iter().collect::<Box<_>>() + } +} + /// The mapping from [`UniqueCrateData`] to their [`Crate`] input. #[derive(Debug, Default)] pub struct CratesMap(DashMap<UniqueCrateData, Crate, BuildHasherDefault<FxHasher>>); @@ -802,33 +857,6 @@ impl CrateGraphBuilder { } } -pub(crate) fn transitive_rev_deps(db: &dyn RootQueryDb, of: Crate) -> FxHashSet<Crate> { - let mut worklist = vec![of]; - let mut rev_deps = FxHashSet::default(); - rev_deps.insert(of); - - let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); - db.all_crates().iter().for_each(|&krate| { - krate - .data(db) - .dependencies - .iter() - .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate)) - }); - - while let Some(krate) = worklist.pop() { - if let Some(crate_rev_deps) = inverted_graph.get(&krate) { - crate_rev_deps - .iter() - .copied() - .filter(|&rev_dep| rev_deps.insert(rev_dep)) - .for_each(|rev_dep| worklist.push(rev_dep)); - } - } - - rev_deps -} - impl BuiltCrateData { pub fn root_file_id(&self, db: &dyn salsa::Database) -> EditionedFileId { EditionedFileId::new(db, self.root_file_id, self.edition) @@ -867,6 +895,10 @@ impl Env { pub fn insert(&mut self, k: impl Into<String>, v: impl Into<String>) -> Option<String> { self.entries.insert(k.into(), v.into()) } + + pub fn contains_key(&self, arg: &str) -> bool { + self.entries.contains_key(arg) + } } impl From<Env> for Vec<(String, String)> { |