From d27dea86b7dd4123f75ad176037b3c754eddfa65 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 3 Jan 2021 12:08:08 +0200 Subject: Properly check assoc items lookup --- crates/hir_def/src/import_map.rs | 105 ++++++++++++++++++++++----------------- 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 { mod tests { use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; use expect_test::{expect, Expect}; - use stdx::format_to; - use crate::{data::FunctionData, test_db::TestDB, AssocContainerId, Lookup}; + use crate::{test_db::TestDB, AssocContainerId, Lookup}; use super::*; @@ -447,46 +446,55 @@ mod tests { let actual = search_dependencies(db.upcast(), krate, query) .into_iter() - .filter_map(|item| { - let mark = match item { - ItemInNs::Types(ModuleDefId::FunctionId(_)) - | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", - ItemInNs::Types(_) => "t", - ItemInNs::Values(_) => "v", - ItemInNs::Macros(_) => "m", + .filter_map(|dependency| { + let dependency_krate = dependency.krate(db.upcast())?; + let dependency_imports = db.import_map(dependency_krate); + + let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) { + Some(assoc_item_path) => (assoc_item_path, "a"), + None => ( + dependency_imports.path_of(dependency)?.to_string(), + match dependency { + ItemInNs::Types(_) => "t", + ItemInNs::Values(_) => "v", + ItemInNs::Macros(_) => "m", + }, + ), }; - item.krate(db.upcast()).map(|krate| { - let map = db.import_map(krate); - - let path = match assoc_to_trait(&db, item) { - Some(trait_) => { - let mut full_path = map.path_of(trait_).unwrap().to_string(); - if let ItemInNs::Types(ModuleDefId::FunctionId(function_id)) - | ItemInNs::Values(ModuleDefId::FunctionId(function_id)) = item - { - format_to!( - full_path, - "::{}", - FunctionData::fn_data_query(&db, function_id).name, - ); - } - full_path - } - None => map.path_of(item).unwrap().to_string(), - }; - - format!( - "{}::{} ({})\n", - crate_graph[krate].display_name.as_ref().unwrap(), - path, - mark - ) - }) + + Some(format!( + "{}::{} ({})\n", + crate_graph[dependency_krate].display_name.as_ref()?, + path, + mark + )) }) .collect::(); expect.assert_eq(&actual) } + fn assoc_item_path( + db: &dyn DefDatabase, + dependency_imports: &ImportMap, + dependency: ItemInNs, + ) -> Option { + let dependency_assoc_item_id = dependency.as_assoc_item_id()?; + let trait_ = assoc_to_trait(db, dependency)?; + if let ModuleDefId::TraitId(tr) = trait_.as_module_def_id()? { + let trait_data = db.trait_data(tr); + let assoc_item_name = + trait_data.items.iter().find_map(|(assoc_item_name, assoc_item_id)| { + if &dependency_assoc_item_id == assoc_item_id { + Some(assoc_item_name) + } else { + None + } + })?; + return Some(format!("{}::{}", dependency_imports.path_of(trait_)?, assoc_item_name)); + } + None + } + fn assoc_to_trait(db: &dyn DefDatabase, item: ItemInNs) -> Option { let assoc: AssocItemId = match item { ItemInNs::Types(it) | ItemInNs::Values(it) => match it { @@ -745,13 +753,17 @@ mod tests { } #[test] - fn fuzzy_import_trait() { + fn fuzzy_import_trait_and_assoc_items() { let ra_fixture = r#" //- /main.rs crate:main deps:dep //- /dep.rs crate:dep pub mod fmt { pub trait Display { - fn format(); + type FmtTypeAlias; + const FMT_CONST: bool; + + fn format_function(); + fn format_method(&self); } } "#; @@ -763,7 +775,10 @@ mod tests { expect![[r#" dep::fmt (t) dep::fmt::Display (t) - dep::fmt::Display::format (f) + dep::fmt::Display::FMT_CONST (a) + dep::fmt::Display::FmtTypeAlias (a) + dep::fmt::Display::format_function (a) + dep::fmt::Display::format_method (a) "#]], ); } @@ -804,8 +819,8 @@ mod tests { dep::Fmt (v) dep::Fmt (m) dep::fmt::Display (t) - dep::fmt::Display::fmt (f) - dep::format (f) + dep::fmt::Display::fmt (a) + dep::format (v) "#]], ); @@ -818,7 +833,7 @@ mod tests { dep::Fmt (t) dep::Fmt (v) dep::Fmt (m) - dep::fmt::Display::fmt (f) + dep::fmt::Display::fmt (a) "#]], ); @@ -832,7 +847,7 @@ mod tests { dep::Fmt (v) dep::Fmt (m) dep::fmt::Display (t) - dep::fmt::Display::fmt (f) + dep::fmt::Display::fmt (a) "#]], ); } @@ -873,7 +888,7 @@ mod tests { dep::Fmt (v) dep::Fmt (m) dep::fmt::Display (t) - dep::fmt::Display::fmt (f) + dep::fmt::Display::fmt (a) "#]], ); @@ -886,7 +901,7 @@ mod tests { dep::Fmt (t) dep::Fmt (v) dep::Fmt (m) - dep::fmt::Display::fmt (f) + dep::fmt::Display::fmt (a) "#]], ); } 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; use rustc_hash::{FxHashMap, FxHashSet}; use test_utils::mark; -use crate::ModuleId; use crate::{ db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, }; +use crate::{AssocItemId, ModuleId}; #[derive(Copy, Clone)] pub(crate) enum ImportType { @@ -349,6 +349,18 @@ impl ItemInNs { } } + pub fn as_assoc_item_id(self) -> Option { + match self { + ItemInNs::Types(ModuleDefId::FunctionId(id)) + | ItemInNs::Values(ModuleDefId::FunctionId(id)) => Some(id.into()), + ItemInNs::Types(ModuleDefId::ConstId(id)) + | ItemInNs::Values(ModuleDefId::ConstId(id)) => Some(id.into()), + ItemInNs::Types(ModuleDefId::TypeAliasId(id)) + | ItemInNs::Values(ModuleDefId::TypeAliasId(id)) => Some(id.into()), + _ => None, + } + } + /// Returns the crate defining this item (or `None` if `self` is built-in). pub fn krate(&self, db: &dyn DefDatabase) -> Option { Some(match self { -- cgit v1.2.3