diff options
author | Kirill Bulatov <[email protected]> | 2021-03-03 21:55:21 +0000 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2021-03-08 21:59:20 +0000 |
commit | 24a5d3b19dfa3e076df8b7413d0cc4a547aeb7d7 (patch) | |
tree | bb49da53786891e9bfd7d063f863416753265d11 /crates/ide_db | |
parent | 33c83e72b9b48177a6171fd06a26676679963a4d (diff) |
Fix the completion labels and tests
Diffstat (limited to 'crates/ide_db')
-rw-r--r-- | crates/ide_db/src/helpers/import_assets.rs | 99 |
1 files changed, 68 insertions, 31 deletions
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index 8d16c011e..b3e90717a 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs | |||
@@ -132,11 +132,17 @@ pub struct LocatedImport { | |||
132 | pub import_path: ModPath, | 132 | pub import_path: ModPath, |
133 | pub item_to_import: ItemInNs, | 133 | pub item_to_import: ItemInNs, |
134 | pub original_item: ItemInNs, | 134 | pub original_item: ItemInNs, |
135 | pub original_path: Option<ModPath>, | ||
135 | } | 136 | } |
136 | 137 | ||
137 | impl LocatedImport { | 138 | impl LocatedImport { |
138 | pub fn new(import_path: ModPath, item_to_import: ItemInNs, original_item: ItemInNs) -> Self { | 139 | pub fn new( |
139 | Self { import_path, item_to_import, original_item } | 140 | import_path: ModPath, |
141 | item_to_import: ItemInNs, | ||
142 | original_item: ItemInNs, | ||
143 | original_path: Option<ModPath>, | ||
144 | ) -> Self { | ||
145 | Self { import_path, item_to_import, original_item, original_path } | ||
140 | } | 146 | } |
141 | 147 | ||
142 | pub fn original_item_name(&self, db: &RootDatabase) -> Option<Name> { | 148 | pub fn original_item_name(&self, db: &RootDatabase) -> Option<Name> { |
@@ -238,7 +244,9 @@ impl<'a> ImportAssets<'a> { | |||
238 | let _p = profile::span("import_assets::applicable_defs"); | 244 | let _p = profile::span("import_assets::applicable_defs"); |
239 | let current_crate = self.module_with_candidate.krate(); | 245 | let current_crate = self.module_with_candidate.krate(); |
240 | 246 | ||
241 | let mod_path = |item| get_mod_path(db, item, &self.module_with_candidate, prefixed); | 247 | let mod_path = |item| { |
248 | get_mod_path(db, item_for_path_search(db, item)?, &self.module_with_candidate, prefixed) | ||
249 | }; | ||
242 | 250 | ||
243 | match &self.import_candidate { | 251 | match &self.import_candidate { |
244 | ImportCandidate::Path(path_candidate) => { | 252 | ImportCandidate::Path(path_candidate) => { |
@@ -276,7 +284,9 @@ fn path_applicable_imports( | |||
276 | Qualifier::Absent => { | 284 | Qualifier::Absent => { |
277 | return items_with_candidate_name | 285 | return items_with_candidate_name |
278 | .into_iter() | 286 | .into_iter() |
279 | .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, item))) | 287 | .filter_map(|item| { |
288 | Some(LocatedImport::new(mod_path(item)?, item, item, mod_path(item))) | ||
289 | }) | ||
280 | .collect(); | 290 | .collect(); |
281 | } | 291 | } |
282 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { | 292 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { |
@@ -300,46 +310,69 @@ fn import_for_item( | |||
300 | original_item: ItemInNs, | 310 | original_item: ItemInNs, |
301 | ) -> Option<LocatedImport> { | 311 | ) -> Option<LocatedImport> { |
302 | let _p = profile::span("import_assets::import_for_item"); | 312 | let _p = profile::span("import_assets::import_for_item"); |
303 | let (item_candidate, trait_to_import) = match original_item.as_module_def_id() { | ||
304 | Some(module_def_id) => { | ||
305 | match ModuleDef::from(module_def_id).as_assoc_item(db).map(|assoc| assoc.container(db)) | ||
306 | { | ||
307 | Some(AssocItemContainer::Trait(trait_)) => { | ||
308 | let trait_item = ItemInNs::from(ModuleDef::from(trait_)); | ||
309 | (trait_item, Some(trait_item)) | ||
310 | } | ||
311 | Some(AssocItemContainer::Impl(impl_)) => { | ||
312 | (ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)), None) | ||
313 | } | ||
314 | None => (original_item, None), | ||
315 | } | ||
316 | } | ||
317 | None => (original_item, None), | ||
318 | }; | ||
319 | let import_path_candidate = mod_path(item_candidate)?; | ||
320 | 313 | ||
314 | let original_item_candidate = item_for_path_search(db, original_item)?; | ||
315 | let import_path_candidate = mod_path(original_item_candidate)?; | ||
321 | let import_path_string = import_path_candidate.to_string(); | 316 | let import_path_string = import_path_candidate.to_string(); |
317 | |||
322 | if !import_path_string.contains(unresolved_first_segment) | 318 | if !import_path_string.contains(unresolved_first_segment) |
323 | || !import_path_string.contains(unresolved_qualifier) | 319 | || !import_path_string.contains(unresolved_qualifier) |
324 | { | 320 | { |
325 | return None; | 321 | return None; |
326 | } | 322 | } |
327 | 323 | ||
328 | let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?; | 324 | let segment_import = |
329 | Some(match (segment_import == item_candidate, trait_to_import) { | 325 | find_import_for_segment(db, original_item_candidate, &unresolved_first_segment)?; |
326 | let trait_item_to_import = original_item | ||
327 | .as_module_def_id() | ||
328 | .and_then(|module_def_id| { | ||
329 | ModuleDef::from(module_def_id).as_assoc_item(db)?.containing_trait(db) | ||
330 | }) | ||
331 | .map(|trait_| ItemInNs::from(ModuleDef::from(trait_))); | ||
332 | Some(match (segment_import == original_item_candidate, trait_item_to_import) { | ||
330 | (true, Some(_)) => { | 333 | (true, Some(_)) => { |
331 | // FIXME we should be able to import both the trait and the segment, | 334 | // FIXME we should be able to import both the trait and the segment, |
332 | // but it's unclear what to do with overlapping edits (merge imports?) | 335 | // but it's unclear what to do with overlapping edits (merge imports?) |
333 | // especially in case of lazy completion edit resolutions. | 336 | // especially in case of lazy completion edit resolutions. |
334 | return None; | 337 | return None; |
335 | } | 338 | } |
336 | (false, Some(trait_to_import)) => { | 339 | (false, Some(trait_to_import)) => LocatedImport::new( |
337 | LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, original_item) | 340 | mod_path(trait_to_import)?, |
338 | } | 341 | trait_to_import, |
339 | (true, None) => LocatedImport::new(import_path_candidate, item_candidate, original_item), | 342 | original_item, |
340 | (false, None) => { | 343 | mod_path(original_item), |
341 | LocatedImport::new(mod_path(segment_import)?, segment_import, original_item) | 344 | ), |
345 | (true, None) => LocatedImport::new( | ||
346 | import_path_candidate, | ||
347 | original_item_candidate, | ||
348 | original_item, | ||
349 | mod_path(original_item), | ||
350 | ), | ||
351 | (false, None) => LocatedImport::new( | ||
352 | mod_path(segment_import)?, | ||
353 | segment_import, | ||
354 | original_item, | ||
355 | mod_path(original_item), | ||
356 | ), | ||
357 | }) | ||
358 | } | ||
359 | |||
360 | fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> { | ||
361 | Some(match item { | ||
362 | ItemInNs::Types(module_def_id) | ItemInNs::Values(module_def_id) => { | ||
363 | let module_def = ModuleDef::from(module_def_id); | ||
364 | |||
365 | match module_def.as_assoc_item(db) { | ||
366 | Some(assoc_item) => match assoc_item.container(db) { | ||
367 | AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)), | ||
368 | AssocItemContainer::Impl(impl_) => { | ||
369 | ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)) | ||
370 | } | ||
371 | }, | ||
372 | None => item, | ||
373 | } | ||
342 | } | 374 | } |
375 | ItemInNs::Macros(_) => item, | ||
343 | }) | 376 | }) |
344 | } | 377 | } |
345 | 378 | ||
@@ -420,10 +453,12 @@ fn trait_applicable_items( | |||
420 | } | 453 | } |
421 | 454 | ||
422 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 455 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
456 | let original_item = assoc_to_item(assoc); | ||
423 | located_imports.insert(LocatedImport::new( | 457 | located_imports.insert(LocatedImport::new( |
424 | mod_path(item)?, | 458 | mod_path(item)?, |
425 | item, | 459 | item, |
426 | assoc_to_item(assoc), | 460 | original_item, |
461 | mod_path(original_item), | ||
427 | )); | 462 | )); |
428 | } | 463 | } |
429 | None::<()> | 464 | None::<()> |
@@ -439,10 +474,12 @@ fn trait_applicable_items( | |||
439 | let assoc = function.as_assoc_item(db)?; | 474 | let assoc = function.as_assoc_item(db)?; |
440 | if required_assoc_items.contains(&assoc) { | 475 | if required_assoc_items.contains(&assoc) { |
441 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 476 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
477 | let original_item = assoc_to_item(assoc); | ||
442 | located_imports.insert(LocatedImport::new( | 478 | located_imports.insert(LocatedImport::new( |
443 | mod_path(item)?, | 479 | mod_path(item)?, |
444 | item, | 480 | item, |
445 | assoc_to_item(assoc), | 481 | original_item, |
482 | mod_path(original_item), | ||
446 | )); | 483 | )); |
447 | } | 484 | } |
448 | None::<()> | 485 | None::<()> |