aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-21 09:51:06 +0000
committerGitHub <[email protected]>2021-03-21 09:51:06 +0000
commit0d40ff5e623b3670ce3e0e324ecbab3e5197aaeb (patch)
treeb376f04aa3bd91eb13007e1a334327a45e45753c /crates/ide_db/src
parent09412d85fc3137d6ada3b27170e14c287f1a1191 (diff)
parentb17d99c0706674c7549aca4670f915aa0b0e2f4e (diff)
Merge #8131
8131: Do smart case fuzzy search during flyimports r=SomeoneToIgnore a=SomeoneToIgnore For now, last actionable part of https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/autoimport.20weirdness Should help https://github.com/rust-analyzer/rust-analyzer/issues/7902 Now during the flyimport completion, if the input is searched case-sensitively, if the input contains any non-lowercase letters; otherwise the lookup done as before, case-insensitively. Co-authored-by: Kirill Bulatov <[email protected]>
Diffstat (limited to 'crates/ide_db/src')
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs3
-rw-r--r--crates/ide_db/src/items_locator.rs39
-rw-r--r--crates/ide_db/src/symbol_index.rs16
3 files changed, 35 insertions, 23 deletions
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index 0da7a1a9d..1881c746f 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -267,7 +267,6 @@ fn path_applicable_imports(
267 AssocItemSearch::Exclude, 267 AssocItemSearch::Exclude,
268 Some(DEFAULT_QUERY_SEARCH_LIMIT), 268 Some(DEFAULT_QUERY_SEARCH_LIMIT),
269 ) 269 )
270 .into_iter()
271 .filter_map(|item| { 270 .filter_map(|item| {
272 let mod_path = mod_path(item)?; 271 let mod_path = mod_path(item)?;
273 Some(LocatedImport::new(mod_path.clone(), item, item, Some(mod_path))) 272 Some(LocatedImport::new(mod_path.clone(), item, item, Some(mod_path)))
@@ -285,7 +284,6 @@ fn path_applicable_imports(
285 AssocItemSearch::Include, 284 AssocItemSearch::Include,
286 Some(DEFAULT_QUERY_SEARCH_LIMIT), 285 Some(DEFAULT_QUERY_SEARCH_LIMIT),
287 ) 286 )
288 .into_iter()
289 .filter_map(|item| { 287 .filter_map(|item| {
290 import_for_item( 288 import_for_item(
291 sema.db, 289 sema.db,
@@ -430,7 +428,6 @@ fn trait_applicable_items(
430 AssocItemSearch::AssocItemsOnly, 428 AssocItemSearch::AssocItemsOnly,
431 Some(DEFAULT_QUERY_SEARCH_LIMIT), 429 Some(DEFAULT_QUERY_SEARCH_LIMIT),
432 ) 430 )
433 .into_iter()
434 .filter_map(|input| item_as_assoc(db, input)) 431 .filter_map(|input| item_as_assoc(db, input))
435 .filter_map(|assoc| { 432 .filter_map(|assoc| {
436 let assoc_item_trait = assoc.containing_trait(db)?; 433 let assoc_item_trait = assoc.containing_trait(db)?;
diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs
index 518cddd74..ef796b6f7 100644
--- a/crates/ide_db/src/items_locator.rs
+++ b/crates/ide_db/src/items_locator.rs
@@ -15,7 +15,6 @@ use crate::{
15 symbol_index::{self, FileSymbol}, 15 symbol_index::{self, FileSymbol},
16 RootDatabase, 16 RootDatabase,
17}; 17};
18use rustc_hash::FxHashSet;
19 18
20/// A value to use, when uncertain which limit to pick. 19/// A value to use, when uncertain which limit to pick.
21pub const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; 20pub const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40;
@@ -32,16 +31,16 @@ pub enum AssocItemSearch {
32} 31}
33 32
34/// Searches for importable items with the given name in the crate and its dependencies. 33/// Searches for importable items with the given name in the crate and its dependencies.
35pub fn items_with_name( 34pub fn items_with_name<'a>(
36 sema: &Semantics<'_, RootDatabase>, 35 sema: &'a Semantics<'_, RootDatabase>,
37 krate: Crate, 36 krate: Crate,
38 name: NameToImport, 37 name: NameToImport,
39 assoc_item_search: AssocItemSearch, 38 assoc_item_search: AssocItemSearch,
40 limit: Option<usize>, 39 limit: Option<usize>,
41) -> FxHashSet<ItemInNs> { 40) -> impl Iterator<Item = ItemInNs> + 'a {
42 let _p = profile::span("items_with_name").detail(|| { 41 let _p = profile::span("items_with_name").detail(|| {
43 format!( 42 format!(
44 "Name: {} ({:?}), crate: {:?}, limit: {:?}", 43 "Name: {}, crate: {:?}, assoc items: {:?}, limit: {:?}",
45 name.text(), 44 name.text(),
46 assoc_item_search, 45 assoc_item_search,
47 krate.display_name(sema.db).map(|name| name.to_string()), 46 krate.display_name(sema.db).map(|name| name.to_string()),
@@ -62,6 +61,8 @@ pub fn items_with_name(
62 (local_query, external_query) 61 (local_query, external_query)
63 } 62 }
64 NameToImport::Fuzzy(fuzzy_search_string) => { 63 NameToImport::Fuzzy(fuzzy_search_string) => {
64 let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone());
65
65 let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) 66 let mut external_query = import_map::Query::new(fuzzy_search_string.clone())
66 .search_mode(import_map::SearchMode::Fuzzy) 67 .search_mode(import_map::SearchMode::Fuzzy)
67 .name_only(); 68 .name_only();
@@ -75,7 +76,12 @@ pub fn items_with_name(
75 } 76 }
76 } 77 }
77 78
78 (symbol_index::Query::new(fuzzy_search_string), external_query) 79 if fuzzy_search_string.to_lowercase() != fuzzy_search_string {
80 local_query.case_sensitive();
81 external_query = external_query.case_sensitive();
82 }
83
84 (local_query, external_query)
79 } 85 }
80 }; 86 };
81 87
@@ -87,13 +93,13 @@ pub fn items_with_name(
87 find_items(sema, krate, assoc_item_search, local_query, external_query) 93 find_items(sema, krate, assoc_item_search, local_query, external_query)
88} 94}
89 95
90fn find_items( 96fn find_items<'a>(
91 sema: &Semantics<'_, RootDatabase>, 97 sema: &'a Semantics<'_, RootDatabase>,
92 krate: Crate, 98 krate: Crate,
93 assoc_item_search: AssocItemSearch, 99 assoc_item_search: AssocItemSearch,
94 local_query: symbol_index::Query, 100 local_query: symbol_index::Query,
95 external_query: import_map::Query, 101 external_query: import_map::Query,
96) -> FxHashSet<ItemInNs> { 102) -> impl Iterator<Item = ItemInNs> + 'a {
97 let _p = profile::span("find_items"); 103 let _p = profile::span("find_items");
98 let db = sema.db; 104 let db = sema.db;
99 105
@@ -108,21 +114,18 @@ fn find_items(
108 // Query the local crate using the symbol index. 114 // Query the local crate using the symbol index.
109 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query) 115 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query)
110 .into_iter() 116 .into_iter()
111 .filter_map(|local_candidate| get_name_definition(sema, &local_candidate)) 117 .filter_map(move |local_candidate| get_name_definition(sema, &local_candidate))
112 .filter_map(|name_definition_to_import| match name_definition_to_import { 118 .filter_map(|name_definition_to_import| match name_definition_to_import {
113 Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)), 119 Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)),
114 Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)), 120 Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)),
115 _ => None, 121 _ => None,
116 }); 122 });
117 123
118 external_importables 124 external_importables.chain(local_results).filter(move |&item| match assoc_item_search {
119 .chain(local_results) 125 AssocItemSearch::Include => true,
120 .filter(move |&item| match assoc_item_search { 126 AssocItemSearch::Exclude => !is_assoc_item(item, sema.db),
121 AssocItemSearch::Include => true, 127 AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db),
122 AssocItemSearch::Exclude => !is_assoc_item(item, sema.db), 128 })
123 AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db),
124 })
125 .collect()
126} 129}
127 130
128fn get_name_definition( 131fn get_name_definition(
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 9ed9568ce..35e382b5c 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -52,6 +52,7 @@ pub struct Query {
52 only_types: bool, 52 only_types: bool,
53 libs: bool, 53 libs: bool,
54 exact: bool, 54 exact: bool,
55 case_sensitive: bool,
55 limit: usize, 56 limit: usize,
56} 57}
57 58
@@ -64,6 +65,7 @@ impl Query {
64 only_types: false, 65 only_types: false,
65 libs: false, 66 libs: false,
66 exact: false, 67 exact: false,
68 case_sensitive: false,
67 limit: usize::max_value(), 69 limit: usize::max_value(),
68 } 70 }
69 } 71 }
@@ -80,6 +82,10 @@ impl Query {
80 self.exact = true; 82 self.exact = true;
81 } 83 }
82 84
85 pub fn case_sensitive(&mut self) {
86 self.case_sensitive = true;
87 }
88
83 pub fn limit(&mut self, limit: usize) { 89 pub fn limit(&mut self, limit: usize) {
84 self.limit = limit 90 self.limit = limit
85 } 91 }
@@ -326,8 +332,14 @@ impl Query {
326 if self.only_types && !symbol.kind.is_type() { 332 if self.only_types && !symbol.kind.is_type() {
327 continue; 333 continue;
328 } 334 }
329 if self.exact && symbol.name != self.query { 335 if self.exact {
330 continue; 336 if symbol.name != self.query {
337 continue;
338 }
339 } else if self.case_sensitive {
340 if self.query.chars().any(|c| !symbol.name.contains(c)) {
341 continue;
342 }
331 } 343 }
332 344
333 res.push(symbol.clone()); 345 res.push(symbol.clone());