aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/completion/src/completions/unqualified_path.rs54
-rw-r--r--crates/completion/src/render.rs1
-rw-r--r--crates/flycheck/Cargo.toml2
-rw-r--r--crates/hir_def/src/import_map.rs82
-rw-r--r--crates/ide_db/src/imports_locator.rs9
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/project_model/Cargo.toml2
7 files changed, 117 insertions, 35 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 4f1c9faa0..3bd776905 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -81,32 +81,34 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
81 81
82 let potential_import_name = ctx.token.to_string(); 82 let potential_import_name = ctx.token.to_string();
83 83
84 let possible_imports = 84 let possible_imports = imports_locator::find_similar_imports(
85 imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, 400) 85 &ctx.sema,
86 .filter_map(|import_candidate| match import_candidate { 86 ctx.krate?,
87 // when completing outside the use declaration, modules are pretty useless 87 &potential_import_name,
88 // and tend to bloat the completion suggestions a lot 88 50,
89 Either::Left(ModuleDef::Module(_)) => None, 89 true,
90 Either::Left(module_def) => Some(( 90 )
91 current_module.find_use_path(ctx.db, module_def)?, 91 .filter_map(|import_candidate| {
92 ScopeDef::ModuleDef(module_def), 92 Some(match import_candidate {
93 )), 93 Either::Left(module_def) => {
94 Either::Right(macro_def) => Some(( 94 (current_module.find_use_path(ctx.db, module_def)?, ScopeDef::ModuleDef(module_def))
95 current_module.find_use_path(ctx.db, macro_def)?, 95 }
96 ScopeDef::MacroDef(macro_def), 96 Either::Right(macro_def) => {
97 )), 97 (current_module.find_use_path(ctx.db, macro_def)?, ScopeDef::MacroDef(macro_def))
98 }) 98 }
99 .filter(|(mod_path, _)| mod_path.len() > 1) 99 })
100 .filter_map(|(import_path, definition)| { 100 })
101 render_resolution_with_import( 101 .filter(|(mod_path, _)| mod_path.len() > 1)
102 RenderContext::new(ctx), 102 .take(20)
103 import_path.clone(), 103 .filter_map(|(import_path, definition)| {
104 import_scope.clone(), 104 render_resolution_with_import(
105 ctx.config.merge, 105 RenderContext::new(ctx),
106 &definition, 106 import_path.clone(),
107 ) 107 import_scope.clone(),
108 }) 108 ctx.config.merge,
109 .take(20); 109 &definition,
110 )
111 });
110 112
111 acc.add_all(possible_imports); 113 acc.add_all(possible_imports);
112 Some(()) 114 Some(())
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index e892d4de8..bce02f577 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -150,6 +150,7 @@ impl<'a> Render<'a> {
150 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 150 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
151 resolution: &ScopeDef, 151 resolution: &ScopeDef,
152 ) -> Option<CompletionItem> { 152 ) -> Option<CompletionItem> {
153 let _p = profile::span("render_resolution");
153 use hir::ModuleDef::*; 154 use hir::ModuleDef::*;
154 155
155 let completion_kind = match resolution { 156 let completion_kind = match resolution {
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml
index 44499bc79..3d9436d69 100644
--- a/crates/flycheck/Cargo.toml
+++ b/crates/flycheck/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13crossbeam-channel = "0.5.0" 13crossbeam-channel = "0.5.0"
14log = "0.4.8" 14log = "0.4.8"
15cargo_metadata = "0.12.0" 15cargo_metadata = "=0.12.0"
16serde_json = "1.0.48" 16serde_json = "1.0.48"
17jod-thread = "0.1.1" 17jod-thread = "0.1.1"
18 18
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index 1e24f29a8..c0f108848 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -7,7 +7,7 @@ use fst::{self, Streamer};
7use hir_expand::name::Name; 7use hir_expand::name::Name;
8use indexmap::{map::Entry, IndexMap}; 8use indexmap::{map::Entry, IndexMap};
9use itertools::Itertools; 9use itertools::Itertools;
10use rustc_hash::{FxHashMap, FxHasher}; 10use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
11use smallvec::SmallVec; 11use smallvec::SmallVec;
12use syntax::SmolStr; 12use syntax::SmolStr;
13 13
@@ -225,6 +225,19 @@ fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo))
225 lhs_str.cmp(&rhs_str) 225 lhs_str.cmp(&rhs_str)
226} 226}
227 227
228#[derive(Debug, Eq, PartialEq, Hash)]
229pub enum ImportKind {
230 Module,
231 Function,
232 Adt,
233 EnumVariant,
234 Const,
235 Static,
236 Trait,
237 TypeAlias,
238 BuiltinType,
239}
240
228#[derive(Debug)] 241#[derive(Debug)]
229pub struct Query { 242pub struct Query {
230 query: String, 243 query: String,
@@ -232,6 +245,7 @@ pub struct Query {
232 anchor_end: bool, 245 anchor_end: bool,
233 case_sensitive: bool, 246 case_sensitive: bool,
234 limit: usize, 247 limit: usize,
248 exclude_import_kinds: FxHashSet<ImportKind>,
235} 249}
236 250
237impl Query { 251impl Query {
@@ -242,6 +256,7 @@ impl Query {
242 anchor_end: false, 256 anchor_end: false,
243 case_sensitive: false, 257 case_sensitive: false,
244 limit: usize::max_value(), 258 limit: usize::max_value(),
259 exclude_import_kinds: FxHashSet::default(),
245 } 260 }
246 } 261 }
247 262
@@ -260,6 +275,12 @@ impl Query {
260 pub fn case_sensitive(self) -> Self { 275 pub fn case_sensitive(self) -> Self {
261 Self { case_sensitive: true, ..self } 276 Self { case_sensitive: true, ..self }
262 } 277 }
278
279 /// Do not include imports of the specified kind in the search results.
280 pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self {
281 self.exclude_import_kinds.insert(import_kind);
282 self
283 }
263} 284}
264 285
265/// Searches dependencies of `krate` for an importable path matching `query`. 286/// Searches dependencies of `krate` for an importable path matching `query`.
@@ -303,10 +324,17 @@ pub fn search_dependencies<'a>(
303 324
304 // Add the items from this `ModPath` group. Those are all subsequent items in 325 // Add the items from this `ModPath` group. Those are all subsequent items in
305 // `importables` whose paths match `path`. 326 // `importables` whose paths match `path`.
306 let iter = importables.iter().copied().take_while(|item| { 327 let iter = importables
307 let item_path = &import_map.map[item].path; 328 .iter()
308 fst_path(item_path) == fst_path(path) 329 .copied()
309 }); 330 .take_while(|item| {
331 let item_path = &import_map.map[item].path;
332 fst_path(item_path) == fst_path(path)
333 })
334 .filter(|&item| match item_import_kind(item) {
335 Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind),
336 None => true,
337 });
310 338
311 if query.case_sensitive { 339 if query.case_sensitive {
312 // FIXME: This does not do a subsequence match. 340 // FIXME: This does not do a subsequence match.
@@ -341,6 +369,20 @@ pub fn search_dependencies<'a>(
341 res 369 res
342} 370}
343 371
372fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
373 Some(match item.as_module_def_id()? {
374 ModuleDefId::ModuleId(_) => ImportKind::Module,
375 ModuleDefId::FunctionId(_) => ImportKind::Function,
376 ModuleDefId::AdtId(_) => ImportKind::Adt,
377 ModuleDefId::EnumVariantId(_) => ImportKind::EnumVariant,
378 ModuleDefId::ConstId(_) => ImportKind::Const,
379 ModuleDefId::StaticId(_) => ImportKind::Static,
380 ModuleDefId::TraitId(_) => ImportKind::Trait,
381 ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias,
382 ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType,
383 })
384}
385
344#[cfg(test)] 386#[cfg(test)]
345mod tests { 387mod tests {
346 use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; 388 use base_db::{fixture::WithFixture, SourceDatabase, Upcast};
@@ -758,4 +800,34 @@ mod tests {
758 "#]], 800 "#]],
759 ); 801 );
760 } 802 }
803
804 #[test]
805 fn search_exclusions() {
806 let ra_fixture = r#"
807 //- /main.rs crate:main deps:dep
808 //- /dep.rs crate:dep
809
810 pub struct fmt;
811 pub struct FMT;
812 "#;
813
814 check_search(
815 ra_fixture,
816 "main",
817 Query::new("FMT"),
818 expect![[r#"
819 dep::fmt (t)
820 dep::fmt (v)
821 dep::FMT (t)
822 dep::FMT (v)
823 "#]],
824 );
825
826 check_search(
827 ra_fixture,
828 "main",
829 Query::new("FMT").exclude_import_kind(ImportKind::Adt),
830 expect![[r#""#]],
831 );
832 }
761} 833}
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs
index 9d8ea7368..09046d3c3 100644
--- a/crates/ide_db/src/imports_locator.rs
+++ b/crates/ide_db/src/imports_locator.rs
@@ -36,8 +36,15 @@ pub fn find_similar_imports<'a>(
36 krate: Crate, 36 krate: Crate,
37 name_to_import: &str, 37 name_to_import: &str,
38 limit: usize, 38 limit: usize,
39 ignore_modules: bool,
39) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { 40) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
40 let _p = profile::span("find_similar_imports"); 41 let _p = profile::span("find_similar_imports");
42
43 let mut external_query = import_map::Query::new(name_to_import).limit(limit);
44 if ignore_modules {
45 external_query = external_query.exclude_import_kind(import_map::ImportKind::Module);
46 }
47
41 find_imports( 48 find_imports(
42 sema, 49 sema,
43 krate, 50 krate,
@@ -46,7 +53,7 @@ pub fn find_similar_imports<'a>(
46 local_query.limit(limit); 53 local_query.limit(limit);
47 local_query 54 local_query
48 }, 55 },
49 import_map::Query::new(name_to_import).limit(limit), 56 external_query,
50 ) 57 )
51} 58}
52 59
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 048b32186..729372968 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -20,7 +20,7 @@ proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
20test_utils = { path = "../test_utils", version = "0.0.0" } 20test_utils = { path = "../test_utils", version = "0.0.0" }
21 21
22[dev-dependencies] 22[dev-dependencies]
23cargo_metadata = "0.12.0" 23cargo_metadata = "=0.12.0"
24difference = "2.0.0" 24difference = "2.0.0"
25 25
26# used as proc macro test targets 26# used as proc macro test targets
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml
index 2d53bcbcc..e0c591603 100644
--- a/crates/project_model/Cargo.toml
+++ b/crates/project_model/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13log = "0.4.8" 13log = "0.4.8"
14rustc-hash = "1.1.0" 14rustc-hash = "1.1.0"
15cargo_metadata = "0.12.0" 15cargo_metadata = "=0.12.0"
16serde = { version = "1.0.106", features = ["derive"] } 16serde = { version = "1.0.106", features = ["derive"] }
17serde_json = "1.0.48" 17serde_json = "1.0.48"
18anyhow = "1.0.26" 18anyhow = "1.0.26"