aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/base_db/src/fixture.rs12
-rw-r--r--crates/base_db/src/input.rs27
-rw-r--r--crates/hir/src/lib.rs23
-rw-r--r--crates/ide/src/references.rs23
-rw-r--r--crates/ide_db/src/search.rs2
-rw-r--r--crates/test_utils/src/fixture.rs15
6 files changed, 94 insertions, 8 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index 5c9824814..cad6866aa 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -57,7 +57,7 @@
57//! fn insert_source_code_here() {} 57//! fn insert_source_code_here() {}
58//! " 58//! "
59//! ``` 59//! ```
60use std::{str::FromStr, sync::Arc}; 60use std::{mem, str::FromStr, sync::Arc};
61 61
62use cfg::CfgOptions; 62use cfg::CfgOptions;
63use rustc_hash::FxHashMap; 63use rustc_hash::FxHashMap;
@@ -148,6 +148,7 @@ impl ChangeFixture {
148 let mut file_set = FileSet::default(); 148 let mut file_set = FileSet::default();
149 let source_root_prefix = "/".to_string(); 149 let source_root_prefix = "/".to_string();
150 let mut file_id = FileId(0); 150 let mut file_id = FileId(0);
151 let mut roots = Vec::new();
151 152
152 let mut file_position = None; 153 let mut file_position = None;
153 154
@@ -168,6 +169,10 @@ impl ChangeFixture {
168 let meta = FileMeta::from(entry); 169 let meta = FileMeta::from(entry);
169 assert!(meta.path.starts_with(&source_root_prefix)); 170 assert!(meta.path.starts_with(&source_root_prefix));
170 171
172 if meta.introduce_new_source_root {
173 roots.push(SourceRoot::new_local(mem::take(&mut file_set)));
174 }
175
171 if let Some(krate) = meta.krate { 176 if let Some(krate) = meta.krate {
172 let crate_name = CrateName::normalize_dashes(&krate); 177 let crate_name = CrateName::normalize_dashes(&krate);
173 let crate_id = crate_graph.add_crate_root( 178 let crate_id = crate_graph.add_crate_root(
@@ -215,7 +220,8 @@ impl ChangeFixture {
215 } 220 }
216 } 221 }
217 222
218 change.set_roots(vec![SourceRoot::new_local(file_set)]); 223 roots.push(SourceRoot::new_local(mem::take(&mut file_set)));
224 change.set_roots(roots);
219 change.set_crate_graph(crate_graph); 225 change.set_crate_graph(crate_graph);
220 226
221 ChangeFixture { file_position, files, change } 227 ChangeFixture { file_position, files, change }
@@ -229,6 +235,7 @@ struct FileMeta {
229 cfg: CfgOptions, 235 cfg: CfgOptions,
230 edition: Edition, 236 edition: Edition,
231 env: Env, 237 env: Env,
238 introduce_new_source_root: bool,
232} 239}
233 240
234impl From<Fixture> for FileMeta { 241impl From<Fixture> for FileMeta {
@@ -247,6 +254,7 @@ impl From<Fixture> for FileMeta {
247 .as_ref() 254 .as_ref()
248 .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()), 255 .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()),
249 env: f.env.into_iter().collect(), 256 env: f.env.into_iter().collect(),
257 introduce_new_source_root: f.introduce_new_source_root,
250 } 258 }
251 } 259 }
252} 260}
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index b5f7e4200..d0def2181 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -274,6 +274,33 @@ impl CrateGraph {
274 deps.into_iter() 274 deps.into_iter()
275 } 275 }
276 276
277 /// Returns an iterator over all transitive reverse dependencies of the given crate.
278 pub fn transitive_reverse_dependencies(
279 &self,
280 of: CrateId,
281 ) -> impl Iterator<Item = CrateId> + '_ {
282 let mut worklist = vec![of];
283 let mut rev_deps = FxHashSet::default();
284 let mut inverted_graph = FxHashMap::<_, Vec<_>>::default();
285 self.arena.iter().for_each(|(&krate, data)| {
286 data.dependencies
287 .iter()
288 .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate))
289 });
290
291 while let Some(krate) = worklist.pop() {
292 if let Some(krate_rev_deps) = inverted_graph.get(&krate) {
293 krate_rev_deps
294 .iter()
295 .copied()
296 .filter(|&rev_dep| rev_deps.insert(rev_dep))
297 .for_each(|rev_dep| worklist.push(rev_dep));
298 }
299 }
300
301 rev_deps.into_iter()
302 }
303
277 /// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate 304 /// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
278 /// come before the crate itself). 305 /// come before the crate itself).
279 pub fn crates_in_topological_order(&self) -> Vec<CrateId> { 306 pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index f0bc2c7b9..ad79a79f8 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -60,6 +60,7 @@ use hir_ty::{
60 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty, 60 InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
61 TyDefId, TyKind, TyVariableKind, 61 TyDefId, TyKind, TyVariableKind,
62}; 62};
63use itertools::Itertools;
63use rustc_hash::FxHashSet; 64use rustc_hash::FxHashSet;
64use stdx::{format_to, impl_from}; 65use stdx::{format_to, impl_from};
65use syntax::{ 66use syntax::{
@@ -141,7 +142,6 @@ impl Crate {
141 .collect() 142 .collect()
142 } 143 }
143 144
144 // FIXME: add `transitive_reverse_dependencies`.
145 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { 145 pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
146 let crate_graph = db.crate_graph(); 146 let crate_graph = db.crate_graph();
147 crate_graph 147 crate_graph
@@ -153,6 +153,14 @@ impl Crate {
153 .collect() 153 .collect()
154 } 154 }
155 155
156 pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
157 db.crate_graph()
158 .transitive_reverse_dependencies(self.id)
159 .into_iter()
160 .map(|id| Crate { id })
161 .collect()
162 }
163
156 pub fn root_module(self, db: &dyn HirDatabase) -> Module { 164 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
157 let def_map = db.crate_def_map(self.id); 165 let def_map = db.crate_def_map(self.id);
158 Module { id: def_map.module_id(def_map.root()) } 166 Module { id: def_map.module_id(def_map.root()) }
@@ -1541,11 +1549,17 @@ impl Impl {
1541 }; 1549 };
1542 1550
1543 let mut all = Vec::new(); 1551 let mut all = Vec::new();
1544 def_crates.into_iter().for_each(|id| { 1552 def_crates.iter().for_each(|&id| {
1545 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1553 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
1546 }); 1554 });
1547 let fp = TyFingerprint::for_impl(&ty.value); 1555 let fp = TyFingerprint::for_impl(&ty.value);
1548 for id in db.crate_graph().iter() { 1556 for id in def_crates
1557 .iter()
1558 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
1559 .map(|Crate { id }| id)
1560 .chain(def_crates.iter().copied())
1561 .unique()
1562 {
1549 match fp { 1563 match fp {
1550 Some(fp) => all.extend( 1564 Some(fp) => all.extend(
1551 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), 1565 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
@@ -1560,7 +1574,8 @@ impl Impl {
1560 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> { 1574 pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
1561 let krate = trait_.module(db).krate(); 1575 let krate = trait_.module(db).krate();
1562 let mut all = Vec::new(); 1576 let mut all = Vec::new();
1563 for Crate { id } in krate.reverse_dependencies(db).into_iter().chain(Some(krate)) { 1577 for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter().chain(Some(krate))
1578 {
1564 let impls = db.trait_impls_in_crate(id); 1579 let impls = db.trait_impls_in_crate(id);
1565 all.extend(impls.for_trait(trait_.id).map(Self::from)) 1580 all.extend(impls.for_trait(trait_.id).map(Self::from))
1566 } 1581 }
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index e8a5666bc..379674530 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1271,4 +1271,27 @@ fn foo(_: bool) -> bo$0ol { true }
1271 "#]], 1271 "#]],
1272 ); 1272 );
1273 } 1273 }
1274
1275 #[test]
1276 fn test_transitive() {
1277 check(
1278 r#"
1279//- /level3.rs new_source_root: crate:level3
1280pub struct Fo$0o;
1281//- /level2.rs new_source_root: crate:level2 deps:level3
1282pub use level3::Foo;
1283//- /level1.rs new_source_root: crate:level1 deps:level2
1284pub use level2::Foo;
1285//- /level0.rs new_source_root: crate:level0 deps:level1
1286pub use level1::Foo;
1287"#,
1288 expect![[r#"
1289 Foo Struct FileId(0) 0..15 11..14
1290
1291 FileId(1) 16..19
1292 FileId(2) 16..19
1293 FileId(3) 16..19
1294 "#]],
1295 );
1296 }
1274} 1297}
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index d00a8b6e7..f56221a6c 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -260,7 +260,7 @@ impl Definition {
260 let mut res = source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>(); 260 let mut res = source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>();
261 261
262 let krate = module.krate(); 262 let krate = module.krate();
263 for rev_dep in krate.reverse_dependencies(db) { 263 for rev_dep in krate.transitive_reverse_dependencies(db) {
264 let root_file = rev_dep.root_file(db); 264 let root_file = rev_dep.root_file(db);
265 let source_root_id = db.file_source_root(root_file); 265 let source_root_id = db.file_source_root(root_file);
266 let source_root = db.source_root(source_root_id); 266 let source_root = db.source_root(source_root_id);
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs
index e3f57f3b2..6bc824e94 100644
--- a/crates/test_utils/src/fixture.rs
+++ b/crates/test_utils/src/fixture.rs
@@ -14,6 +14,7 @@ pub struct Fixture {
14 pub cfg_key_values: Vec<(String, String)>, 14 pub cfg_key_values: Vec<(String, String)>,
15 pub edition: Option<String>, 15 pub edition: Option<String>,
16 pub env: FxHashMap<String, String>, 16 pub env: FxHashMap<String, String>,
17 pub introduce_new_source_root: bool,
17} 18}
18 19
19impl Fixture { 20impl Fixture {
@@ -70,6 +71,7 @@ impl Fixture {
70 let mut cfg_atoms = Vec::new(); 71 let mut cfg_atoms = Vec::new();
71 let mut cfg_key_values = Vec::new(); 72 let mut cfg_key_values = Vec::new();
72 let mut env = FxHashMap::default(); 73 let mut env = FxHashMap::default();
74 let mut introduce_new_source_root = false;
73 for component in components[1..].iter() { 75 for component in components[1..].iter() {
74 let (key, value) = split_once(component, ':').unwrap(); 76 let (key, value) = split_once(component, ':').unwrap();
75 match key { 77 match key {
@@ -91,11 +93,22 @@ impl Fixture {
91 } 93 }
92 } 94 }
93 } 95 }
96 "new_source_root" => introduce_new_source_root = true,
94 _ => panic!("bad component: {:?}", component), 97 _ => panic!("bad component: {:?}", component),
95 } 98 }
96 } 99 }
97 100
98 Fixture { path, text: String::new(), krate, deps, cfg_atoms, cfg_key_values, edition, env } 101 Fixture {
102 path,
103 text: String::new(),
104 krate,
105 deps,
106 cfg_atoms,
107 cfg_key_values,
108 edition,
109 env,
110 introduce_new_source_root,
111 }
99 } 112 }
100} 113}
101 114