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.rs112
1 files changed, 82 insertions, 30 deletions
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index cac74778a2..240f126491 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -351,6 +351,8 @@ pub struct CrateData<Id> {
/// declared in source via `extern crate test`.
pub dependencies: Vec<Dependency<Id>>,
pub origin: CrateOrigin,
+ /// Extra crate-level attributes, including the surrounding `#![]`.
+ pub crate_attrs: Box<[Box<str>]>,
pub is_proc_macro: bool,
/// The working directory to run proc-macros in invoked in the context of this crate.
/// This is the workspace root of the cargo workspace for workspace members, the crate manifest
@@ -460,6 +462,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) -> Vec<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
+ }
+
+ /// 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>>);
@@ -475,6 +532,7 @@ impl CrateGraphBuilder {
mut potential_cfg_options: Option<CfgOptions>,
mut env: Env,
origin: CrateOrigin,
+ crate_attrs: Vec<String>,
is_proc_macro: bool,
proc_macro_cwd: Arc<AbsPathBuf>,
ws_data: Arc<CrateWorkspaceData>,
@@ -484,12 +542,17 @@ impl CrateGraphBuilder {
if let Some(potential_cfg_options) = &mut potential_cfg_options {
potential_cfg_options.shrink_to_fit();
}
+ let crate_attrs: Vec<_> = crate_attrs
+ .into_iter()
+ .map(|raw_attr| format!("#![{raw_attr}]").into_boxed_str())
+ .collect();
self.arena.alloc(CrateBuilder {
basic: CrateData {
root_file_id,
edition,
dependencies: Vec::new(),
origin,
+ crate_attrs: crate_attrs.into_boxed_slice(),
is_proc_macro,
proc_macro_cwd,
},
@@ -593,6 +656,7 @@ impl CrateGraphBuilder {
edition: krate.basic.edition,
is_proc_macro: krate.basic.is_proc_macro,
origin: krate.basic.origin.clone(),
+ crate_attrs: krate.basic.crate_attrs.clone(),
root_file_id: krate.basic.root_file_id,
proc_macro_cwd: krate.basic.proc_macro_cwd.clone(),
};
@@ -802,36 +866,10 @@ 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)
+impl Crate {
+ pub fn root_file_id(self, db: &dyn salsa::Database) -> EditionedFileId {
+ let data = self.data(db);
+ EditionedFileId::new(db, data.root_file_id, data.edition, self)
}
}
@@ -867,6 +905,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)> {
@@ -942,6 +984,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -955,6 +998,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -968,6 +1012,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1001,6 +1046,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1014,6 +1060,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1042,6 +1089,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1055,6 +1103,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1068,6 +1117,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1096,6 +1146,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
@@ -1109,6 +1160,7 @@ mod tests {
Default::default(),
Env::default(),
CrateOrigin::Local { repo: None, name: None },
+ Vec::new(),
false,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),