aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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/display.rs3
-rw-r--r--crates/ide/src/display/navigation_target.rs30
-rw-r--r--crates/ide/src/display/short_label.rs128
-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
9 files changed, 110 insertions, 153 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/display.rs b/crates/ide/src/display.rs
index 1f7b665c0..71e97d6b4 100644
--- a/crates/ide/src/display.rs
+++ b/crates/ide/src/display.rs
@@ -2,8 +2,7 @@
2//! into types that may be used to render in a UI. 2//! into types that may be used to render in a UI.
3 3
4pub(crate) mod navigation_target; 4pub(crate) mod navigation_target;
5mod short_label;
6 5
7pub(crate) use navigation_target::{ToNav, TryToNav}; 6pub(crate) use navigation_target::{ToNav, TryToNav};
8 7
9pub(crate) use syntax::display::{function_declaration, macro_label}; 8pub(crate) use syntax::display::macro_label;
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 69c3751a1..c086de163 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -5,9 +5,10 @@ use std::fmt;
5use either::Either; 5use either::Either;
6use hir::{ 6use hir::{
7 AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource, 7 AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource,
8 Semantics,
8}; 9};
9use ide_db::{ 10use ide_db::{
10 base_db::{FileId, FileRange, SourceDatabase}, 11 base_db::{FileId, FileRange},
11 symbol_index::FileSymbolKind, 12 symbol_index::FileSymbolKind,
12 SymbolKind, 13 SymbolKind,
13}; 14};
@@ -19,8 +20,6 @@ use syntax::{
19 20
20use crate::FileSymbol; 21use crate::FileSymbol;
21 22
22use super::short_label::ShortLabel;
23
24/// `NavigationTarget` represents and element in the editor's UI which you can 23/// `NavigationTarget` represents and element in the editor's UI which you can
25/// click on to navigate to a particular piece of code. 24/// click on to navigate to a particular piece of code.
26/// 25///
@@ -502,21 +501,22 @@ impl TryToNav for hir::ConstParam {
502/// 501///
503/// e.g. `struct Name`, `enum Name`, `fn Name` 502/// e.g. `struct Name`, `enum Name`, `fn Name`
504pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { 503pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
505 let parse = db.parse(symbol.file_id); 504 let sema = Semantics::new(db);
506 let node = symbol.ptr.to_node(parse.tree().syntax()); 505 let parse = sema.parse(symbol.file_id);
506 let node = symbol.ptr.to_node(parse.syntax());
507 507
508 match_ast! { 508 match_ast! {
509 match node { 509 match node {
510 ast::Fn(it) => it.short_label(), 510 ast::Fn(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
511 ast::Struct(it) => it.short_label(), 511 ast::Struct(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
512 ast::Enum(it) => it.short_label(), 512 ast::Enum(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
513 ast::Trait(it) => it.short_label(), 513 ast::Trait(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
514 ast::Module(it) => it.short_label(), 514 ast::Module(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
515 ast::TypeAlias(it) => it.short_label(), 515 ast::TypeAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
516 ast::Const(it) => it.short_label(), 516 ast::Const(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
517 ast::Static(it) => it.short_label(), 517 ast::Static(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
518 ast::RecordField(it) => it.short_label(), 518 ast::RecordField(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
519 ast::Variant(it) => it.short_label(), 519 ast::Variant(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
520 _ => None, 520 _ => None,
521 } 521 }
522 } 522 }
diff --git a/crates/ide/src/display/short_label.rs b/crates/ide/src/display/short_label.rs
deleted file mode 100644
index 2df9266b4..000000000
--- a/crates/ide/src/display/short_label.rs
+++ /dev/null
@@ -1,128 +0,0 @@
1//! FIXME: write short doc here
2
3use stdx::format_to;
4use syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
5
6pub(crate) trait ShortLabel {
7 fn short_label(&self) -> Option<String>;
8}
9
10impl ShortLabel for ast::Fn {
11 fn short_label(&self) -> Option<String> {
12 Some(crate::display::function_declaration(self))
13 }
14}
15
16impl ShortLabel for ast::Struct {
17 fn short_label(&self) -> Option<String> {
18 short_label_from_node(self, "struct ")
19 }
20}
21
22impl ShortLabel for ast::Union {
23 fn short_label(&self) -> Option<String> {
24 short_label_from_node(self, "union ")
25 }
26}
27
28impl ShortLabel for ast::Enum {
29 fn short_label(&self) -> Option<String> {
30 short_label_from_node(self, "enum ")
31 }
32}
33
34impl ShortLabel for ast::Trait {
35 fn short_label(&self) -> Option<String> {
36 if self.unsafe_token().is_some() {
37 short_label_from_node(self, "unsafe trait ")
38 } else {
39 short_label_from_node(self, "trait ")
40 }
41 }
42}
43
44impl ShortLabel for ast::Module {
45 fn short_label(&self) -> Option<String> {
46 short_label_from_node(self, "mod ")
47 }
48}
49
50impl ShortLabel for ast::SourceFile {
51 fn short_label(&self) -> Option<String> {
52 None
53 }
54}
55
56impl ShortLabel for ast::BlockExpr {
57 fn short_label(&self) -> Option<String> {
58 None
59 }
60}
61
62impl ShortLabel for ast::TypeAlias {
63 fn short_label(&self) -> Option<String> {
64 let mut buf = short_label_from_node(self, "type ")?;
65 if let Some(type_ref) = self.ty() {
66 format_to!(buf, " = {}", type_ref.syntax());
67 }
68 Some(buf)
69 }
70}
71
72impl ShortLabel for ast::Const {
73 fn short_label(&self) -> Option<String> {
74 short_label_from_ty(self, self.ty(), "const ")
75 }
76}
77
78impl ShortLabel for ast::Static {
79 fn short_label(&self) -> Option<String> {
80 short_label_from_ty(self, self.ty(), "static ")
81 }
82}
83
84impl ShortLabel for ast::RecordField {
85 fn short_label(&self) -> Option<String> {
86 short_label_from_ty(self, self.ty(), "")
87 }
88}
89
90impl ShortLabel for ast::Variant {
91 fn short_label(&self) -> Option<String> {
92 Some(self.name()?.text().to_string())
93 }
94}
95
96impl ShortLabel for ast::ConstParam {
97 fn short_label(&self) -> Option<String> {
98 let mut buf = "const ".to_owned();
99 buf.push_str(self.name()?.text());
100 if let Some(type_ref) = self.ty() {
101 format_to!(buf, ": {}", type_ref.syntax());
102 }
103 Some(buf)
104 }
105}
106
107fn short_label_from_ty<T>(node: &T, ty: Option<ast::Type>, prefix: &str) -> Option<String>
108where
109 T: NameOwner + VisibilityOwner,
110{
111 let mut buf = short_label_from_node(node, prefix)?;
112
113 if let Some(type_ref) = ty {
114 format_to!(buf, ": {}", type_ref.syntax());
115 }
116
117 Some(buf)
118}
119
120fn short_label_from_node<T>(node: &T, label: &str) -> Option<String>
121where
122 T: NameOwner + VisibilityOwner,
123{
124 let mut buf = node.visibility().map(|v| format!("{} ", v.syntax())).unwrap_or_default();
125 buf.push_str(label);
126 buf.push_str(node.name()?.text());
127 Some(buf)
128}
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