Properly check assoc items lookup

This commit is contained in:
Kirill Bulatov 2021-01-03 12:08:08 +02:00
parent 63d83fa385
commit d27dea86b7
2 changed files with 72 additions and 45 deletions

View file

@ -428,9 +428,8 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
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::<String>();
expect.assert_eq(&actual)
}
fn assoc_item_path(
db: &dyn DefDatabase,
dependency_imports: &ImportMap,
dependency: ItemInNs,
) -> Option<String> {
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<ItemInNs> {
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)
"#]],
);
}

View file

@ -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<AssocItemId> {
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<CrateId> {
Some(match self {