Add associated data into fst

This commit is contained in:
Kirill Bulatov 2021-01-02 02:05:09 +02:00
parent 1bfc3a50c0
commit 63d83fa385

View File

@ -7,9 +7,7 @@
use hir_expand::name::Name;
use indexmap::{map::Entry, IndexMap};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
use smallvec::SmallVec;
use syntax::SmolStr;
use rustc_hash::{FxHashSet, FxHasher};
use crate::{
db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId,
@ -25,6 +23,8 @@ pub struct ImportInfo {
pub path: ImportPath,
/// The module containing this item.
pub container: ModuleId,
/// Whether the import is a trait associated item or not.
pub is_assoc_item: bool,
}
#[derive(Debug, Clone, Eq, PartialEq)]
@ -64,10 +64,6 @@ pub struct ImportMap {
/// the index of the first one.
importables: Vec<ItemInNs>,
fst: fst::Map<Vec<u8>>,
/// Maps names of associated items to the item's ID. Only includes items whose defining trait is
/// exported.
assoc_map: FxHashMap<SmolStr, SmallVec<[AssocItemId; 1]>>,
}
impl ImportMap {
@ -108,14 +104,22 @@ pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
for item in per_ns.iter_items() {
let path = mk_path();
let path_len = path.len();
let import_info = ImportInfo { path, container: module, is_assoc_item: false };
// If we've added a path to a trait, add the trait's associated items to the assoc map.
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
import_map.collect_trait_assoc_items(db, tr, &import_info);
}
match import_map.map.entry(item) {
Entry::Vacant(entry) => {
entry.insert(ImportInfo { path, container: module });
entry.insert(import_info);
}
Entry::Occupied(mut entry) => {
// If the new path is shorter, prefer that one.
if path.len() < entry.get().path.len() {
*entry.get_mut() = ImportInfo { path, container: module };
if path_len < entry.get().path.len() {
*entry.get_mut() = import_info;
} else {
continue;
}
@ -128,11 +132,6 @@ pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
worklist.push((mod_id, mk_path()));
}
// If we've added a path to a trait, add the trait's methods to the method map.
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
import_map.collect_trait_methods(db, tr);
}
}
}
}
@ -153,12 +152,10 @@ pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
}
}
let start = last_batch_start;
let key = fst_path(&importables[last_batch_start].1.path);
builder.insert(key, last_batch_start as u64).unwrap();
last_batch_start = idx + 1;
let key = fst_path(&importables[start].1.path);
builder.insert(key, start as u64).unwrap();
}
import_map.fst = fst::Map::new(builder.into_inner().unwrap()).unwrap();
@ -176,10 +173,22 @@ pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> {
self.map.get(&item)
}
fn collect_trait_methods(&mut self, db: &dyn DefDatabase, tr: TraitId) {
let data = db.trait_data(tr);
for (name, item) in data.items.iter() {
self.assoc_map.entry(name.to_string().into()).or_default().push(*item);
fn collect_trait_assoc_items(
&mut self,
db: &dyn DefDatabase,
tr: TraitId,
import_info: &ImportInfo,
) {
for (assoc_item_name, item) in db.trait_data(tr).items.iter() {
let assoc_item = ItemInNs::Types(match item.clone() {
AssocItemId::FunctionId(f) => f.into(),
AssocItemId::ConstId(c) => c.into(),
AssocItemId::TypeAliasId(t) => t.into(),
});
let mut assoc_item_info = import_info.to_owned();
assoc_item_info.path.segments.push(assoc_item_name.to_owned());
assoc_item_info.is_assoc_item = true;
self.map.insert(assoc_item, assoc_item_info);
}
}
}
@ -304,11 +313,11 @@ pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self {
}
}
fn contains_query(query: &Query, input_path: &ImportPath, enforce_lowercase: bool) -> bool {
let mut input = if query.name_only {
input_path.segments.last().unwrap().to_string()
fn import_matches_query(import: &ImportInfo, query: &Query, enforce_lowercase: bool) -> bool {
let mut input = if import.is_assoc_item || query.name_only {
import.path.segments.last().unwrap().to_string()
} else {
input_path.to_string()
import.path.to_string()
};
if enforce_lowercase || !query.case_sensitive {
input.make_ascii_lowercase();
@ -366,13 +375,13 @@ pub fn search_dependencies<'a>(
let import_map = &import_maps[indexed_value.index];
let importables = &import_map.importables[indexed_value.value as usize..];
// Path shared by the importable items in this group.
let common_importables_path = &import_map.map[&importables[0]].path;
if !contains_query(&query, common_importables_path, true) {
let common_importable_data = &import_map.map[&importables[0]];
if !import_matches_query(common_importable_data, &query, true) {
continue;
}
let common_importables_path_fst = fst_path(common_importables_path);
// Path shared by the importable items in this group.
let common_importables_path_fst = fst_path(&common_importable_data.path);
// Add the items from this `ModPath` group. Those are all subsequent items in
// `importables` whose paths match `path`.
let iter = importables
@ -387,7 +396,7 @@ pub fn search_dependencies<'a>(
})
.filter(|item| {
!query.case_sensitive // we've already checked the common importables path case-insensitively
|| contains_query(&query, &import_map.map[item].path, false)
|| import_matches_query(&import_map.map[item], &query, false)
});
res.extend(iter);
@ -398,19 +407,6 @@ pub fn search_dependencies<'a>(
}
}
// Add all exported associated items whose names match the query (exactly).
for map in &import_maps {
if let Some(v) = map.assoc_map.get(&*query.query) {
res.extend(v.iter().map(|&assoc| {
ItemInNs::Types(match assoc {
AssocItemId::FunctionId(it) => it.into(),
AssocItemId::ConstId(it) => it.into(),
AssocItemId::TypeAliasId(it) => it.into(),
})
}));
}
}
res
}
@ -755,7 +751,7 @@ fn fuzzy_import_trait() {
//- /dep.rs crate:dep
pub mod fmt {
pub trait Display {
fn fmttt();
fn format();
}
}
"#;
@ -767,7 +763,7 @@ pub trait Display {
expect![[r#"
dep::fmt (t)
dep::fmt::Display (t)
dep::fmt::Display::fmttt (f)
dep::fmt::Display::format (f)
"#]],
);
}
@ -808,8 +804,8 @@ pub mod fmt {
dep::Fmt (v)
dep::Fmt (m)
dep::fmt::Display (t)
dep::format (f)
dep::fmt::Display::fmt (f)
dep::format (f)
"#]],
);