aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/helpers/import_assets.rs
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2021-03-03 21:55:21 +0000
committerKirill Bulatov <[email protected]>2021-03-08 21:59:20 +0000
commit24a5d3b19dfa3e076df8b7413d0cc4a547aeb7d7 (patch)
treebb49da53786891e9bfd7d063f863416753265d11 /crates/ide_db/src/helpers/import_assets.rs
parent33c83e72b9b48177a6171fd06a26676679963a4d (diff)
Fix the completion labels and tests
Diffstat (limited to 'crates/ide_db/src/helpers/import_assets.rs')
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs99
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
137impl LocatedImport { 138impl 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
360fn 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::<()>