diff options
author | Kirill Bulatov <[email protected]> | 2021-01-03 10:08:08 +0000 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2021-01-04 15:44:27 +0000 |
commit | d27dea86b7dd4123f75ad176037b3c754eddfa65 (patch) | |
tree | ae11b6934630892583ea68031536d1d590f2b06e /crates/hir_def | |
parent | 63d83fa38584fa0537f896bee5d90709c1352030 (diff) |
Properly check assoc items lookup
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/import_map.rs | 105 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 14 |
2 files changed, 73 insertions, 46 deletions
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 6283c1f1a..0ba8198b5 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -428,9 +428,8 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> { | |||
428 | mod tests { | 428 | mod tests { |
429 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 429 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
430 | use expect_test::{expect, Expect}; | 430 | use expect_test::{expect, Expect}; |
431 | use stdx::format_to; | ||
432 | 431 | ||
433 | use crate::{data::FunctionData, test_db::TestDB, AssocContainerId, Lookup}; | 432 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; |
434 | 433 | ||
435 | use super::*; | 434 | use super::*; |
436 | 435 | ||
@@ -447,46 +446,55 @@ mod tests { | |||
447 | 446 | ||
448 | let actual = search_dependencies(db.upcast(), krate, query) | 447 | let actual = search_dependencies(db.upcast(), krate, query) |
449 | .into_iter() | 448 | .into_iter() |
450 | .filter_map(|item| { | 449 | .filter_map(|dependency| { |
451 | let mark = match item { | 450 | let dependency_krate = dependency.krate(db.upcast())?; |
452 | ItemInNs::Types(ModuleDefId::FunctionId(_)) | 451 | let dependency_imports = db.import_map(dependency_krate); |
453 | | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", | 452 | |
454 | ItemInNs::Types(_) => "t", | 453 | let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) { |
455 | ItemInNs::Values(_) => "v", | 454 | Some(assoc_item_path) => (assoc_item_path, "a"), |
456 | ItemInNs::Macros(_) => "m", | 455 | None => ( |
456 | dependency_imports.path_of(dependency)?.to_string(), | ||
457 | match dependency { | ||
458 | ItemInNs::Types(_) => "t", | ||
459 | ItemInNs::Values(_) => "v", | ||
460 | ItemInNs::Macros(_) => "m", | ||
461 | }, | ||
462 | ), | ||
457 | }; | 463 | }; |
458 | item.krate(db.upcast()).map(|krate| { | 464 | |
459 | let map = db.import_map(krate); | 465 | Some(format!( |
460 | 466 | "{}::{} ({})\n", | |
461 | let path = match assoc_to_trait(&db, item) { | 467 | crate_graph[dependency_krate].display_name.as_ref()?, |
462 | Some(trait_) => { | 468 | path, |
463 | let mut full_path = map.path_of(trait_).unwrap().to_string(); | 469 | mark |
464 | if let ItemInNs::Types(ModuleDefId::FunctionId(function_id)) | 470 | )) |
465 | | ItemInNs::Values(ModuleDefId::FunctionId(function_id)) = item | ||
466 | { | ||
467 | format_to!( | ||
468 | full_path, | ||
469 | "::{}", | ||
470 | FunctionData::fn_data_query(&db, function_id).name, | ||
471 | ); | ||
472 | } | ||
473 | full_path | ||
474 | } | ||
475 | None => map.path_of(item).unwrap().to_string(), | ||
476 | }; | ||
477 | |||
478 | format!( | ||
479 | "{}::{} ({})\n", | ||
480 | crate_graph[krate].display_name.as_ref().unwrap(), | ||
481 | path, | ||
482 | mark | ||
483 | ) | ||
484 | }) | ||
485 | }) | 471 | }) |
486 | .collect::<String>(); | 472 | .collect::<String>(); |
487 | expect.assert_eq(&actual) | 473 | expect.assert_eq(&actual) |
488 | } | 474 | } |
489 | 475 | ||
476 | fn assoc_item_path( | ||
477 | db: &dyn DefDatabase, | ||
478 | dependency_imports: &ImportMap, | ||
479 | dependency: ItemInNs, | ||
480 | ) -> Option<String> { | ||
481 | let dependency_assoc_item_id = dependency.as_assoc_item_id()?; | ||
482 | let trait_ = assoc_to_trait(db, dependency)?; | ||
483 | if let ModuleDefId::TraitId(tr) = trait_.as_module_def_id()? { | ||
484 | let trait_data = db.trait_data(tr); | ||
485 | let assoc_item_name = | ||
486 | trait_data.items.iter().find_map(|(assoc_item_name, assoc_item_id)| { | ||
487 | if &dependency_assoc_item_id == assoc_item_id { | ||
488 | Some(assoc_item_name) | ||
489 | } else { | ||
490 | None | ||
491 | } | ||
492 | })?; | ||
493 | return Some(format!("{}::{}", dependency_imports.path_of(trait_)?, assoc_item_name)); | ||
494 | } | ||
495 | None | ||
496 | } | ||
497 | |||
490 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { | 498 | fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option<ItemInNs> { |
491 | let assoc: AssocItemId = match item { | 499 | let assoc: AssocItemId = match item { |
492 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { | 500 | ItemInNs::Types(it) | ItemInNs::Values(it) => match it { |
@@ -745,13 +753,17 @@ mod tests { | |||
745 | } | 753 | } |
746 | 754 | ||
747 | #[test] | 755 | #[test] |
748 | fn fuzzy_import_trait() { | 756 | fn fuzzy_import_trait_and_assoc_items() { |
749 | let ra_fixture = r#" | 757 | let ra_fixture = r#" |
750 | //- /main.rs crate:main deps:dep | 758 | //- /main.rs crate:main deps:dep |
751 | //- /dep.rs crate:dep | 759 | //- /dep.rs crate:dep |
752 | pub mod fmt { | 760 | pub mod fmt { |
753 | pub trait Display { | 761 | pub trait Display { |
754 | fn format(); | 762 | type FmtTypeAlias; |
763 | const FMT_CONST: bool; | ||
764 | |||
765 | fn format_function(); | ||
766 | fn format_method(&self); | ||
755 | } | 767 | } |
756 | } | 768 | } |
757 | "#; | 769 | "#; |
@@ -763,7 +775,10 @@ mod tests { | |||
763 | expect![[r#" | 775 | expect![[r#" |
764 | dep::fmt (t) | 776 | dep::fmt (t) |
765 | dep::fmt::Display (t) | 777 | dep::fmt::Display (t) |
766 | dep::fmt::Display::format (f) | 778 | dep::fmt::Display::FMT_CONST (a) |
779 | dep::fmt::Display::FmtTypeAlias (a) | ||
780 | dep::fmt::Display::format_function (a) | ||
781 | dep::fmt::Display::format_method (a) | ||
767 | "#]], | 782 | "#]], |
768 | ); | 783 | ); |
769 | } | 784 | } |
@@ -804,8 +819,8 @@ mod tests { | |||
804 | dep::Fmt (v) | 819 | dep::Fmt (v) |
805 | dep::Fmt (m) | 820 | dep::Fmt (m) |
806 | dep::fmt::Display (t) | 821 | dep::fmt::Display (t) |
807 | dep::fmt::Display::fmt (f) | 822 | dep::fmt::Display::fmt (a) |
808 | dep::format (f) | 823 | dep::format (v) |
809 | "#]], | 824 | "#]], |
810 | ); | 825 | ); |
811 | 826 | ||
@@ -818,7 +833,7 @@ mod tests { | |||
818 | dep::Fmt (t) | 833 | dep::Fmt (t) |
819 | dep::Fmt (v) | 834 | dep::Fmt (v) |
820 | dep::Fmt (m) | 835 | dep::Fmt (m) |
821 | dep::fmt::Display::fmt (f) | 836 | dep::fmt::Display::fmt (a) |
822 | "#]], | 837 | "#]], |
823 | ); | 838 | ); |
824 | 839 | ||
@@ -832,7 +847,7 @@ mod tests { | |||
832 | dep::Fmt (v) | 847 | dep::Fmt (v) |
833 | dep::Fmt (m) | 848 | dep::Fmt (m) |
834 | dep::fmt::Display (t) | 849 | dep::fmt::Display (t) |
835 | dep::fmt::Display::fmt (f) | 850 | dep::fmt::Display::fmt (a) |
836 | "#]], | 851 | "#]], |
837 | ); | 852 | ); |
838 | } | 853 | } |
@@ -873,7 +888,7 @@ mod tests { | |||
873 | dep::Fmt (v) | 888 | dep::Fmt (v) |
874 | dep::Fmt (m) | 889 | dep::Fmt (m) |
875 | dep::fmt::Display (t) | 890 | dep::fmt::Display (t) |
876 | dep::fmt::Display::fmt (f) | 891 | dep::fmt::Display::fmt (a) |
877 | "#]], | 892 | "#]], |
878 | ); | 893 | ); |
879 | 894 | ||
@@ -886,7 +901,7 @@ mod tests { | |||
886 | dep::Fmt (t) | 901 | dep::Fmt (t) |
887 | dep::Fmt (v) | 902 | dep::Fmt (v) |
888 | dep::Fmt (m) | 903 | dep::Fmt (m) |
889 | dep::fmt::Display::fmt (f) | 904 | dep::fmt::Display::fmt (a) |
890 | "#]], | 905 | "#]], |
891 | ); | 906 | ); |
892 | } | 907 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 62ab3b2bd..4da1c3ab0 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -10,11 +10,11 @@ use once_cell::sync::Lazy; | |||
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use test_utils::mark; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::ModuleId; | ||
14 | use crate::{ | 13 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 14 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, | 15 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, |
17 | }; | 16 | }; |
17 | use crate::{AssocItemId, ModuleId}; | ||
18 | 18 | ||
19 | #[derive(Copy, Clone)] | 19 | #[derive(Copy, Clone)] |
20 | pub(crate) enum ImportType { | 20 | pub(crate) enum ImportType { |
@@ -349,6 +349,18 @@ impl ItemInNs { | |||
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | pub fn as_assoc_item_id(self) -> Option<AssocItemId> { | ||
353 | match self { | ||
354 | ItemInNs::Types(ModuleDefId::FunctionId(id)) | ||
355 | | ItemInNs::Values(ModuleDefId::FunctionId(id)) => Some(id.into()), | ||
356 | ItemInNs::Types(ModuleDefId::ConstId(id)) | ||
357 | | ItemInNs::Values(ModuleDefId::ConstId(id)) => Some(id.into()), | ||
358 | ItemInNs::Types(ModuleDefId::TypeAliasId(id)) | ||
359 | | ItemInNs::Values(ModuleDefId::TypeAliasId(id)) => Some(id.into()), | ||
360 | _ => None, | ||
361 | } | ||
362 | } | ||
363 | |||
352 | /// Returns the crate defining this item (or `None` if `self` is built-in). | 364 | /// Returns the crate defining this item (or `None` if `self` is built-in). |
353 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | 365 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { |
354 | Some(match self { | 366 | Some(match self { |