diff options
Diffstat (limited to 'crates/ide_db')
-rw-r--r-- | crates/ide_db/src/helpers/import_assets.rs | 155 | ||||
-rw-r--r-- | crates/ide_db/src/items_locator.rs (renamed from crates/ide_db/src/imports_locator.rs) | 75 | ||||
-rw-r--r-- | crates/ide_db/src/lib.rs | 2 |
3 files changed, 101 insertions, 131 deletions
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index a30a4dd9d..8d16c011e 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs | |||
@@ -1,14 +1,13 @@ | |||
1 | //! Look up accessible paths for items. | 1 | //! Look up accessible paths for items. |
2 | use either::Either; | ||
3 | use hir::{ | 2 | use hir::{ |
4 | AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module, | 3 | AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module, |
5 | ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type, | 4 | ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type, |
6 | }; | 5 | }; |
7 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
8 | use syntax::{ast, AstNode}; | 7 | use syntax::{ast, AstNode}; |
9 | 8 | ||
10 | use crate::{ | 9 | use crate::{ |
11 | imports_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT}, | 10 | items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT}, |
12 | RootDatabase, | 11 | RootDatabase, |
13 | }; | 12 | }; |
14 | 13 | ||
@@ -130,34 +129,23 @@ impl<'a> ImportAssets<'a> { | |||
130 | 129 | ||
131 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 130 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
132 | pub struct LocatedImport { | 131 | pub struct LocatedImport { |
133 | import_path: ModPath, | 132 | pub import_path: ModPath, |
134 | item_to_import: ItemInNs, | 133 | pub item_to_import: ItemInNs, |
135 | data_to_display: Option<(ModPath, ItemInNs)>, | 134 | pub original_item: ItemInNs, |
136 | } | 135 | } |
137 | 136 | ||
138 | impl LocatedImport { | 137 | impl LocatedImport { |
139 | pub fn new( | 138 | pub fn new(import_path: ModPath, item_to_import: ItemInNs, original_item: ItemInNs) -> Self { |
140 | import_path: ModPath, | 139 | Self { import_path, item_to_import, original_item } |
141 | item_to_import: ItemInNs, | ||
142 | data_to_display: Option<(ModPath, ItemInNs)>, | ||
143 | ) -> Self { | ||
144 | Self { import_path, item_to_import, data_to_display } | ||
145 | } | 140 | } |
146 | 141 | ||
147 | pub fn display_path(&self) -> &ModPath { | 142 | pub fn original_item_name(&self, db: &RootDatabase) -> Option<Name> { |
148 | self.data_to_display.as_ref().map(|(mod_path, _)| mod_path).unwrap_or(&self.import_path) | 143 | match self.original_item { |
149 | } | 144 | ItemInNs::Types(module_def_id) | ItemInNs::Values(module_def_id) => { |
150 | 145 | ModuleDef::from(module_def_id).name(db) | |
151 | pub fn import_path(&self) -> &ModPath { | 146 | } |
152 | &self.import_path | 147 | ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).name(db), |
153 | } | 148 | } |
154 | |||
155 | pub fn item_to_display(&self) -> ItemInNs { | ||
156 | self.data_to_display.as_ref().map(|&(_, item)| item).unwrap_or(self.item_to_import) | ||
157 | } | ||
158 | |||
159 | pub fn item_to_import(&self) -> ItemInNs { | ||
160 | self.item_to_import | ||
161 | } | 149 | } |
162 | } | 150 | } |
163 | 151 | ||
@@ -166,25 +154,20 @@ impl<'a> ImportAssets<'a> { | |||
166 | &self.import_candidate | 154 | &self.import_candidate |
167 | } | 155 | } |
168 | 156 | ||
169 | fn name_to_import(&self) -> &NameToImport { | ||
170 | match &self.import_candidate { | ||
171 | ImportCandidate::Path(candidate) => &candidate.name, | ||
172 | ImportCandidate::TraitAssocItem(candidate) | ||
173 | | ImportCandidate::TraitMethod(candidate) => &candidate.name, | ||
174 | } | ||
175 | } | ||
176 | |||
177 | pub fn search_for_imports( | 157 | pub fn search_for_imports( |
178 | &self, | 158 | &self, |
179 | sema: &Semantics<RootDatabase>, | 159 | sema: &Semantics<RootDatabase>, |
180 | prefix_kind: PrefixKind, | 160 | prefix_kind: PrefixKind, |
181 | ) -> Vec<LocatedImport> { | 161 | ) -> FxHashSet<LocatedImport> { |
182 | let _p = profile::span("import_assets::search_for_imports"); | 162 | let _p = profile::span("import_assets::search_for_imports"); |
183 | self.search_for(sema, Some(prefix_kind)) | 163 | self.search_for(sema, Some(prefix_kind)) |
184 | } | 164 | } |
185 | 165 | ||
186 | /// This may return non-absolute paths if a part of the returned path is already imported into scope. | 166 | /// This may return non-absolute paths if a part of the returned path is already imported into scope. |
187 | pub fn search_for_relative_paths(&self, sema: &Semantics<RootDatabase>) -> Vec<LocatedImport> { | 167 | pub fn search_for_relative_paths( |
168 | &self, | ||
169 | sema: &Semantics<RootDatabase>, | ||
170 | ) -> FxHashSet<LocatedImport> { | ||
188 | let _p = profile::span("import_assets::search_for_relative_paths"); | 171 | let _p = profile::span("import_assets::search_for_relative_paths"); |
189 | self.search_for(sema, None) | 172 | self.search_for(sema, None) |
190 | } | 173 | } |
@@ -193,14 +176,13 @@ impl<'a> ImportAssets<'a> { | |||
193 | &self, | 176 | &self, |
194 | sema: &Semantics<RootDatabase>, | 177 | sema: &Semantics<RootDatabase>, |
195 | prefixed: Option<PrefixKind>, | 178 | prefixed: Option<PrefixKind>, |
196 | ) -> Vec<LocatedImport> { | 179 | ) -> FxHashSet<LocatedImport> { |
197 | let current_crate = self.module_with_candidate.krate(); | 180 | let items_with_candidate_name = match self.name_to_import() { |
198 | let scope_definitions = self.scope_definitions(); | 181 | NameToImport::Exact(exact_name) => items_locator::with_for_exact_name( |
199 | 182 | sema, | |
200 | let defs_for_candidate_name = match self.name_to_import() { | 183 | self.module_with_candidate.krate(), |
201 | NameToImport::Exact(exact_name) => { | 184 | exact_name.clone(), |
202 | imports_locator::find_exact_imports(sema, current_crate, exact_name.clone()) | 185 | ), |
203 | } | ||
204 | // FIXME: ideally, we should avoid using `fst` for seacrhing trait imports for assoc items: | 186 | // FIXME: ideally, we should avoid using `fst` for seacrhing trait imports for assoc items: |
205 | // instead, we need to look up all trait impls for a certain struct and search through them only | 187 | // instead, we need to look up all trait impls for a certain struct and search through them only |
206 | // see https://github.com/rust-analyzer/rust-analyzer/pull/7293#issuecomment-761585032 | 188 | // see https://github.com/rust-analyzer/rust-analyzer/pull/7293#issuecomment-761585032 |
@@ -213,9 +195,9 @@ impl<'a> ImportAssets<'a> { | |||
213 | (AssocItemSearch::Include, Some(DEFAULT_QUERY_SEARCH_LIMIT)) | 195 | (AssocItemSearch::Include, Some(DEFAULT_QUERY_SEARCH_LIMIT)) |
214 | }; | 196 | }; |
215 | 197 | ||
216 | imports_locator::find_similar_imports( | 198 | items_locator::with_similar_name( |
217 | sema, | 199 | sema, |
218 | current_crate, | 200 | self.module_with_candidate.krate(), |
219 | fuzzy_name.clone(), | 201 | fuzzy_name.clone(), |
220 | assoc_item_search, | 202 | assoc_item_search, |
221 | limit, | 203 | limit, |
@@ -223,10 +205,11 @@ impl<'a> ImportAssets<'a> { | |||
223 | } | 205 | } |
224 | }; | 206 | }; |
225 | 207 | ||
226 | self.applicable_defs(sema.db, prefixed, defs_for_candidate_name) | 208 | let scope_definitions = self.scope_definitions(); |
209 | self.applicable_defs(sema.db, prefixed, items_with_candidate_name) | ||
227 | .into_iter() | 210 | .into_iter() |
228 | .filter(|import| import.import_path().len() > 1) | 211 | .filter(|import| import.import_path.len() > 1) |
229 | .filter(|import| !scope_definitions.contains(&ScopeDef::from(import.item_to_import()))) | 212 | .filter(|import| !scope_definitions.contains(&ScopeDef::from(import.item_to_import))) |
230 | .collect() | 213 | .collect() |
231 | } | 214 | } |
232 | 215 | ||
@@ -238,11 +221,19 @@ impl<'a> ImportAssets<'a> { | |||
238 | scope_definitions | 221 | scope_definitions |
239 | } | 222 | } |
240 | 223 | ||
224 | fn name_to_import(&self) -> &NameToImport { | ||
225 | match &self.import_candidate { | ||
226 | ImportCandidate::Path(candidate) => &candidate.name, | ||
227 | ImportCandidate::TraitAssocItem(candidate) | ||
228 | | ImportCandidate::TraitMethod(candidate) => &candidate.name, | ||
229 | } | ||
230 | } | ||
231 | |||
241 | fn applicable_defs( | 232 | fn applicable_defs( |
242 | &self, | 233 | &self, |
243 | db: &RootDatabase, | 234 | db: &RootDatabase, |
244 | prefixed: Option<PrefixKind>, | 235 | prefixed: Option<PrefixKind>, |
245 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 236 | items_with_candidate_name: FxHashSet<ItemInNs>, |
246 | ) -> FxHashSet<LocatedImport> { | 237 | ) -> FxHashSet<LocatedImport> { |
247 | let _p = profile::span("import_assets::applicable_defs"); | 238 | let _p = profile::span("import_assets::applicable_defs"); |
248 | let current_crate = self.module_with_candidate.krate(); | 239 | let current_crate = self.module_with_candidate.krate(); |
@@ -251,7 +242,7 @@ impl<'a> ImportAssets<'a> { | |||
251 | 242 | ||
252 | match &self.import_candidate { | 243 | match &self.import_candidate { |
253 | ImportCandidate::Path(path_candidate) => { | 244 | ImportCandidate::Path(path_candidate) => { |
254 | path_applicable_imports(db, path_candidate, mod_path, defs_for_candidate_name) | 245 | path_applicable_imports(db, path_candidate, mod_path, items_with_candidate_name) |
255 | } | 246 | } |
256 | ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items( | 247 | ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items( |
257 | db, | 248 | db, |
@@ -259,7 +250,7 @@ impl<'a> ImportAssets<'a> { | |||
259 | trait_candidate, | 250 | trait_candidate, |
260 | true, | 251 | true, |
261 | mod_path, | 252 | mod_path, |
262 | defs_for_candidate_name, | 253 | items_with_candidate_name, |
263 | ), | 254 | ), |
264 | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( | 255 | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( |
265 | db, | 256 | db, |
@@ -267,7 +258,7 @@ impl<'a> ImportAssets<'a> { | |||
267 | trait_candidate, | 258 | trait_candidate, |
268 | false, | 259 | false, |
269 | mod_path, | 260 | mod_path, |
270 | defs_for_candidate_name, | 261 | items_with_candidate_name, |
271 | ), | 262 | ), |
272 | } | 263 | } |
273 | } | 264 | } |
@@ -277,17 +268,15 @@ fn path_applicable_imports( | |||
277 | db: &RootDatabase, | 268 | db: &RootDatabase, |
278 | path_candidate: &PathImportCandidate, | 269 | path_candidate: &PathImportCandidate, |
279 | mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy, | 270 | mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy, |
280 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 271 | items_with_candidate_name: FxHashSet<ItemInNs>, |
281 | ) -> FxHashSet<LocatedImport> { | 272 | ) -> FxHashSet<LocatedImport> { |
282 | let _p = profile::span("import_assets::path_applicable_imports"); | 273 | let _p = profile::span("import_assets::path_applicable_imports"); |
283 | 274 | ||
284 | let items_for_candidate_name = | ||
285 | defs_for_candidate_name.map(|def| def.either(ItemInNs::from, ItemInNs::from)); | ||
286 | |||
287 | let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier { | 275 | let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier { |
288 | Qualifier::Absent => { | 276 | Qualifier::Absent => { |
289 | return items_for_candidate_name | 277 | return items_with_candidate_name |
290 | .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, None))) | 278 | .into_iter() |
279 | .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, item))) | ||
291 | .collect(); | 280 | .collect(); |
292 | } | 281 | } |
293 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { | 282 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { |
@@ -295,7 +284,8 @@ fn path_applicable_imports( | |||
295 | } | 284 | } |
296 | }; | 285 | }; |
297 | 286 | ||
298 | items_for_candidate_name | 287 | items_with_candidate_name |
288 | .into_iter() | ||
299 | .filter_map(|item| { | 289 | .filter_map(|item| { |
300 | import_for_item(db, mod_path, &unresolved_first_segment, &unresolved_qualifier, item) | 290 | import_for_item(db, mod_path, &unresolved_first_segment, &unresolved_qualifier, item) |
301 | }) | 291 | }) |
@@ -336,7 +326,6 @@ fn import_for_item( | |||
336 | } | 326 | } |
337 | 327 | ||
338 | let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?; | 328 | let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?; |
339 | let data_to_display = Some((import_path_candidate.clone(), original_item)); | ||
340 | Some(match (segment_import == item_candidate, trait_to_import) { | 329 | Some(match (segment_import == item_candidate, trait_to_import) { |
341 | (true, Some(_)) => { | 330 | (true, Some(_)) => { |
342 | // FIXME we should be able to import both the trait and the segment, | 331 | // FIXME we should be able to import both the trait and the segment, |
@@ -345,11 +334,11 @@ fn import_for_item( | |||
345 | return None; | 334 | return None; |
346 | } | 335 | } |
347 | (false, Some(trait_to_import)) => { | 336 | (false, Some(trait_to_import)) => { |
348 | LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, data_to_display) | 337 | LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, original_item) |
349 | } | 338 | } |
350 | (true, None) => LocatedImport::new(import_path_candidate, item_candidate, data_to_display), | 339 | (true, None) => LocatedImport::new(import_path_candidate, item_candidate, original_item), |
351 | (false, None) => { | 340 | (false, None) => { |
352 | LocatedImport::new(mod_path(segment_import)?, segment_import, data_to_display) | 341 | LocatedImport::new(mod_path(segment_import)?, segment_import, original_item) |
353 | } | 342 | } |
354 | }) | 343 | }) |
355 | } | 344 | } |
@@ -399,16 +388,14 @@ fn trait_applicable_items( | |||
399 | trait_candidate: &TraitImportCandidate, | 388 | trait_candidate: &TraitImportCandidate, |
400 | trait_assoc_item: bool, | 389 | trait_assoc_item: bool, |
401 | mod_path: impl Fn(ItemInNs) -> Option<ModPath>, | 390 | mod_path: impl Fn(ItemInNs) -> Option<ModPath>, |
402 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 391 | items_with_candidate_name: FxHashSet<ItemInNs>, |
403 | ) -> FxHashSet<LocatedImport> { | 392 | ) -> FxHashSet<LocatedImport> { |
404 | let _p = profile::span("import_assets::trait_applicable_items"); | 393 | let _p = profile::span("import_assets::trait_applicable_items"); |
405 | let mut required_assoc_items = FxHashSet::default(); | 394 | let mut required_assoc_items = FxHashSet::default(); |
406 | 395 | ||
407 | let trait_candidates = defs_for_candidate_name | 396 | let trait_candidates = items_with_candidate_name |
408 | .filter_map(|input| match input { | 397 | .into_iter() |
409 | Either::Left(module_def) => module_def.as_assoc_item(db), | 398 | .filter_map(|input| ModuleDef::from(input.as_module_def_id()?).as_assoc_item(db)) |
410 | _ => None, | ||
411 | }) | ||
412 | .filter_map(|assoc| { | 399 | .filter_map(|assoc| { |
413 | let assoc_item_trait = assoc.containing_trait(db)?; | 400 | let assoc_item_trait = assoc.containing_trait(db)?; |
414 | required_assoc_items.insert(assoc); | 401 | required_assoc_items.insert(assoc); |
@@ -433,20 +420,10 @@ fn trait_applicable_items( | |||
433 | } | 420 | } |
434 | 421 | ||
435 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 422 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
436 | let item_path = mod_path(item)?; | ||
437 | |||
438 | let assoc_item = assoc_to_item(assoc); | ||
439 | let assoc_item_path = match assoc.container(db) { | ||
440 | AssocItemContainer::Trait(_) => item_path.clone(), | ||
441 | AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from( | ||
442 | ModuleDef::from(impl_.target_ty(db).as_adt()?), | ||
443 | ))?, | ||
444 | }; | ||
445 | |||
446 | located_imports.insert(LocatedImport::new( | 423 | located_imports.insert(LocatedImport::new( |
447 | item_path, | 424 | mod_path(item)?, |
448 | item, | 425 | item, |
449 | Some((assoc_item_path, assoc_item)), | 426 | assoc_to_item(assoc), |
450 | )); | 427 | )); |
451 | } | 428 | } |
452 | None::<()> | 429 | None::<()> |
@@ -462,20 +439,10 @@ fn trait_applicable_items( | |||
462 | let assoc = function.as_assoc_item(db)?; | 439 | let assoc = function.as_assoc_item(db)?; |
463 | if required_assoc_items.contains(&assoc) { | 440 | if required_assoc_items.contains(&assoc) { |
464 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 441 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
465 | let item_path = mod_path(item)?; | ||
466 | |||
467 | let assoc_item = assoc_to_item(assoc); | ||
468 | let assoc_item_path = match assoc.container(db) { | ||
469 | AssocItemContainer::Trait(_) => item_path.clone(), | ||
470 | AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from( | ||
471 | ModuleDef::from(impl_.target_ty(db).as_adt()?), | ||
472 | ))?, | ||
473 | }; | ||
474 | |||
475 | located_imports.insert(LocatedImport::new( | 442 | located_imports.insert(LocatedImport::new( |
476 | item_path, | 443 | mod_path(item)?, |
477 | item, | 444 | item, |
478 | Some((assoc_item_path, assoc_item)), | 445 | assoc_to_item(assoc), |
479 | )); | 446 | )); |
480 | } | 447 | } |
481 | None::<()> | 448 | None::<()> |
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/items_locator.rs index fd700e04f..b81c14618 100644 --- a/crates/ide_db/src/imports_locator.rs +++ b/crates/ide_db/src/items_locator.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | //! This module contains an import search functionality that is provided to the assists module. | 1 | //! This module contains an import search functionality that is provided to the assists module. |
2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. | 2 | //! Later, this should be moved away to a separate crate that is accessible from the assists module. |
3 | 3 | ||
4 | use either::Either; | ||
4 | use hir::{ | 5 | use hir::{ |
5 | import_map::{self, ImportKind}, | 6 | import_map::{self, ImportKind}, |
6 | AsAssocItem, Crate, MacroDef, ModuleDef, Semantics, | 7 | AsAssocItem, Crate, ItemInNs, ModuleDef, Semantics, |
7 | }; | 8 | }; |
8 | use syntax::{ast, AstNode, SyntaxKind::NAME}; | 9 | use syntax::{ast, AstNode, SyntaxKind::NAME}; |
9 | 10 | ||
@@ -12,32 +13,31 @@ use crate::{ | |||
12 | symbol_index::{self, FileSymbol}, | 13 | symbol_index::{self, FileSymbol}, |
13 | RootDatabase, | 14 | RootDatabase, |
14 | }; | 15 | }; |
15 | use either::Either; | ||
16 | use rustc_hash::FxHashSet; | 16 | use rustc_hash::FxHashSet; |
17 | 17 | ||
18 | pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; | 18 | pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; |
19 | 19 | ||
20 | pub fn find_exact_imports( | 20 | pub fn with_for_exact_name( |
21 | sema: &Semantics<'_, RootDatabase>, | 21 | sema: &Semantics<'_, RootDatabase>, |
22 | krate: Crate, | 22 | krate: Crate, |
23 | name_to_import: String, | 23 | exact_name: String, |
24 | ) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>>> { | 24 | ) -> FxHashSet<ItemInNs> { |
25 | let _p = profile::span("find_exact_imports"); | 25 | let _p = profile::span("find_exact_imports"); |
26 | Box::new(find_imports( | 26 | find_items( |
27 | sema, | 27 | sema, |
28 | krate, | 28 | krate, |
29 | { | 29 | { |
30 | let mut local_query = symbol_index::Query::new(name_to_import.clone()); | 30 | let mut local_query = symbol_index::Query::new(exact_name.clone()); |
31 | local_query.exact(); | 31 | local_query.exact(); |
32 | local_query.limit(DEFAULT_QUERY_SEARCH_LIMIT); | 32 | local_query.limit(DEFAULT_QUERY_SEARCH_LIMIT); |
33 | local_query | 33 | local_query |
34 | }, | 34 | }, |
35 | import_map::Query::new(name_to_import) | 35 | import_map::Query::new(exact_name) |
36 | .limit(DEFAULT_QUERY_SEARCH_LIMIT) | 36 | .limit(DEFAULT_QUERY_SEARCH_LIMIT) |
37 | .name_only() | 37 | .name_only() |
38 | .search_mode(import_map::SearchMode::Equals) | 38 | .search_mode(import_map::SearchMode::Equals) |
39 | .case_sensitive(), | 39 | .case_sensitive(), |
40 | )) | 40 | ) |
41 | } | 41 | } |
42 | 42 | ||
43 | #[derive(Debug)] | 43 | #[derive(Debug)] |
@@ -47,13 +47,13 @@ pub enum AssocItemSearch { | |||
47 | AssocItemsOnly, | 47 | AssocItemsOnly, |
48 | } | 48 | } |
49 | 49 | ||
50 | pub fn find_similar_imports<'a>( | 50 | pub fn with_similar_name( |
51 | sema: &'a Semantics<'a, RootDatabase>, | 51 | sema: &Semantics<'_, RootDatabase>, |
52 | krate: Crate, | 52 | krate: Crate, |
53 | fuzzy_search_string: String, | 53 | fuzzy_search_string: String, |
54 | assoc_item_search: AssocItemSearch, | 54 | assoc_item_search: AssocItemSearch, |
55 | limit: Option<usize>, | 55 | limit: Option<usize>, |
56 | ) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>> + 'a> { | 56 | ) -> FxHashSet<ItemInNs> { |
57 | let _p = profile::span("find_similar_imports"); | 57 | let _p = profile::span("find_similar_imports"); |
58 | 58 | ||
59 | let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) | 59 | let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) |
@@ -77,36 +77,39 @@ pub fn find_similar_imports<'a>( | |||
77 | local_query.limit(limit); | 77 | local_query.limit(limit); |
78 | } | 78 | } |
79 | 79 | ||
80 | Box::new(find_imports(sema, krate, local_query, external_query).filter( | 80 | find_items(sema, krate, local_query, external_query) |
81 | move |import_candidate| match assoc_item_search { | 81 | .into_iter() |
82 | .filter(move |&item| match assoc_item_search { | ||
82 | AssocItemSearch::Include => true, | 83 | AssocItemSearch::Include => true, |
83 | AssocItemSearch::Exclude => !is_assoc_item(import_candidate, sema.db), | 84 | AssocItemSearch::Exclude => !is_assoc_item(item, sema.db), |
84 | AssocItemSearch::AssocItemsOnly => is_assoc_item(import_candidate, sema.db), | 85 | AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db), |
85 | }, | 86 | }) |
86 | )) | 87 | .collect() |
87 | } | 88 | } |
88 | 89 | ||
89 | fn is_assoc_item(import_candidate: &Either<ModuleDef, MacroDef>, db: &RootDatabase) -> bool { | 90 | fn is_assoc_item(item: ItemInNs, db: &RootDatabase) -> bool { |
90 | match import_candidate { | 91 | item.as_module_def_id() |
91 | Either::Left(ModuleDef::Function(function)) => function.as_assoc_item(db).is_some(), | 92 | .and_then(|module_def_id| ModuleDef::from(module_def_id).as_assoc_item(db)) |
92 | Either::Left(ModuleDef::Const(const_)) => const_.as_assoc_item(db).is_some(), | 93 | .is_some() |
93 | Either::Left(ModuleDef::TypeAlias(type_alias)) => type_alias.as_assoc_item(db).is_some(), | ||
94 | _ => false, | ||
95 | } | ||
96 | } | 94 | } |
97 | 95 | ||
98 | fn find_imports<'a>( | 96 | fn find_items( |
99 | sema: &Semantics<'a, RootDatabase>, | 97 | sema: &Semantics<'_, RootDatabase>, |
100 | krate: Crate, | 98 | krate: Crate, |
101 | local_query: symbol_index::Query, | 99 | local_query: symbol_index::Query, |
102 | external_query: import_map::Query, | 100 | external_query: import_map::Query, |
103 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | 101 | ) -> FxHashSet<ItemInNs> { |
104 | let _p = profile::span("find_similar_imports"); | 102 | let _p = profile::span("find_similar_imports"); |
105 | let db = sema.db; | 103 | let db = sema.db; |
106 | 104 | ||
107 | // Query dependencies first. | 105 | // Query dependencies first. |
108 | let mut candidates: FxHashSet<_> = | 106 | let mut candidates = krate |
109 | krate.query_external_importables(db, external_query).collect(); | 107 | .query_external_importables(db, external_query) |
108 | .map(|external_importable| match external_importable { | ||
109 | Either::Left(module_def) => ItemInNs::from(module_def), | ||
110 | Either::Right(macro_def) => ItemInNs::from(macro_def), | ||
111 | }) | ||
112 | .collect::<FxHashSet<_>>(); | ||
110 | 113 | ||
111 | // Query the local crate using the symbol index. | 114 | // Query the local crate using the symbol index. |
112 | 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); |
@@ -114,19 +117,19 @@ fn find_imports<'a>( | |||
114 | candidates.extend( | 117 | candidates.extend( |
115 | local_results | 118 | local_results |
116 | .into_iter() | 119 | .into_iter() |
117 | .filter_map(|import_candidate| get_name_definition(sema, &import_candidate)) | 120 | .filter_map(|local_candidate| get_name_definition(sema, &local_candidate)) |
118 | .filter_map(|name_definition_to_import| match name_definition_to_import { | 121 | .filter_map(|name_definition_to_import| match name_definition_to_import { |
119 | Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), | 122 | Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)), |
120 | Definition::Macro(macro_def) => Some(Either::Right(macro_def)), | 123 | Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)), |
121 | _ => None, | 124 | _ => None, |
122 | }), | 125 | }), |
123 | ); | 126 | ); |
124 | 127 | ||
125 | candidates.into_iter() | 128 | candidates |
126 | } | 129 | } |
127 | 130 | ||
128 | fn get_name_definition<'a>( | 131 | fn get_name_definition( |
129 | sema: &Semantics<'a, RootDatabase>, | 132 | sema: &Semantics<'_, RootDatabase>, |
130 | import_candidate: &FileSymbol, | 133 | import_candidate: &FileSymbol, |
131 | ) -> Option<Definition> { | 134 | ) -> Option<Definition> { |
132 | let _p = profile::span("get_name_definition"); | 135 | let _p = profile::span("get_name_definition"); |
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs index 6eb34b06b..88ee4a87d 100644 --- a/crates/ide_db/src/lib.rs +++ b/crates/ide_db/src/lib.rs | |||
@@ -8,7 +8,7 @@ pub mod line_index; | |||
8 | pub mod symbol_index; | 8 | pub mod symbol_index; |
9 | pub mod defs; | 9 | pub mod defs; |
10 | pub mod search; | 10 | pub mod search; |
11 | pub mod imports_locator; | 11 | pub mod items_locator; |
12 | pub mod source_change; | 12 | pub mod source_change; |
13 | pub mod ty_filter; | 13 | pub mod ty_filter; |
14 | pub mod traits; | 14 | pub mod traits; |