Add more profiling for flyimports
This commit is contained in:
parent
f4da4de7cd
commit
3aaf07b8cb
@ -120,6 +120,7 @@ fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> {
|
||||
}
|
||||
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
|
||||
let _p = profile::span("relevant_crates");
|
||||
let source_root = self.0.file_source_root(file_id);
|
||||
self.0.source_root_crates(source_root)
|
||||
}
|
||||
|
@ -191,6 +191,7 @@ pub fn query_external_importables(
|
||||
db: &dyn DefDatabase,
|
||||
query: import_map::Query,
|
||||
) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
|
||||
let _p = profile::span("query_external_importables");
|
||||
import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item {
|
||||
ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
|
||||
ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
|
||||
@ -2185,6 +2186,7 @@ pub fn iterate_method_candidates<T>(
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let _p = profile::span("iterate_method_candidates");
|
||||
// There should be no inference vars in types passed here
|
||||
// FIXME check that?
|
||||
// FIXME replace Unknown by bound vars here
|
||||
@ -2218,6 +2220,7 @@ pub fn iterate_path_candidates<T>(
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let _p = profile::span("iterate_path_candidates");
|
||||
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
||||
|
||||
let env = self.env.clone();
|
||||
@ -2255,6 +2258,7 @@ pub fn applicable_inherent_traits<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn HirDatabase,
|
||||
) -> impl Iterator<Item = Trait> + 'a {
|
||||
let _p = profile::span("applicable_inherent_traits");
|
||||
self.autoderef(db)
|
||||
.filter_map(|derefed_type| derefed_type.ty.dyn_trait())
|
||||
.flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
|
||||
|
@ -69,80 +69,10 @@ pub struct ImportMap {
|
||||
impl ImportMap {
|
||||
pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
|
||||
let _p = profile::span("import_map_query");
|
||||
let def_map = db.crate_def_map(krate);
|
||||
let mut import_map = Self::default();
|
||||
|
||||
// We look only into modules that are public(ly reexported), starting with the crate root.
|
||||
let empty = ImportPath { segments: vec![] };
|
||||
let root = def_map.module_id(def_map.root());
|
||||
let mut worklist = vec![(root, empty)];
|
||||
while let Some((module, mod_path)) = worklist.pop() {
|
||||
let ext_def_map;
|
||||
let mod_data = if module.krate == krate {
|
||||
&def_map[module.local_id]
|
||||
} else {
|
||||
// The crate might reexport a module defined in another crate.
|
||||
ext_def_map = module.def_map(db);
|
||||
&ext_def_map[module.local_id]
|
||||
};
|
||||
|
||||
let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| {
|
||||
let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public);
|
||||
if per_ns.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some((name, per_ns))
|
||||
}
|
||||
});
|
||||
|
||||
for (name, per_ns) in visible_items {
|
||||
let mk_path = || {
|
||||
let mut path = mod_path.clone();
|
||||
path.segments.push(name.clone());
|
||||
path
|
||||
};
|
||||
|
||||
for item in per_ns.iter_items() {
|
||||
let path = mk_path();
|
||||
let path_len = path.len();
|
||||
let import_info =
|
||||
ImportInfo { path, container: module, is_trait_assoc_item: false };
|
||||
|
||||
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
|
||||
import_map.collect_trait_assoc_items(
|
||||
db,
|
||||
tr,
|
||||
matches!(item, ItemInNs::Types(_)),
|
||||
&import_info,
|
||||
);
|
||||
}
|
||||
|
||||
match import_map.map.entry(item) {
|
||||
Entry::Vacant(entry) => {
|
||||
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() = import_info;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we've just added a path to a module, descend into it. We might traverse
|
||||
// modules multiple times, but only if the new path to it is shorter than the
|
||||
// first (else we `continue` above).
|
||||
if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
|
||||
worklist.push((mod_id, mk_path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut import_map = collect_import_map(db, krate);
|
||||
|
||||
let mut importables = import_map.map.iter().collect::<Vec<_>>();
|
||||
|
||||
importables.sort_by(cmp);
|
||||
|
||||
// Build the FST, taking care not to insert duplicate values.
|
||||
@ -185,6 +115,7 @@ fn collect_trait_assoc_items(
|
||||
is_type_in_ns: bool,
|
||||
original_import_info: &ImportInfo,
|
||||
) {
|
||||
let _p = profile::span("collect_trait_assoc_items");
|
||||
for (assoc_item_name, item) in &db.trait_data(tr).items {
|
||||
let module_def_id = match item {
|
||||
AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
|
||||
@ -210,6 +141,84 @@ fn collect_trait_assoc_items(
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap {
|
||||
let _p = profile::span("collect_import_map");
|
||||
|
||||
let def_map = db.crate_def_map(krate);
|
||||
let mut import_map = ImportMap::default();
|
||||
|
||||
// We look only into modules that are public(ly reexported), starting with the crate root.
|
||||
let empty = ImportPath { segments: vec![] };
|
||||
let root = def_map.module_id(def_map.root());
|
||||
let mut worklist = vec![(root, empty)];
|
||||
while let Some((module, mod_path)) = worklist.pop() {
|
||||
let ext_def_map;
|
||||
let mod_data = if module.krate == krate {
|
||||
&def_map[module.local_id]
|
||||
} else {
|
||||
// The crate might reexport a module defined in another crate.
|
||||
ext_def_map = module.def_map(db);
|
||||
&ext_def_map[module.local_id]
|
||||
};
|
||||
|
||||
let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| {
|
||||
let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public);
|
||||
if per_ns.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some((name, per_ns))
|
||||
}
|
||||
});
|
||||
|
||||
for (name, per_ns) in visible_items {
|
||||
let mk_path = || {
|
||||
let mut path = mod_path.clone();
|
||||
path.segments.push(name.clone());
|
||||
path
|
||||
};
|
||||
|
||||
for item in per_ns.iter_items() {
|
||||
let path = mk_path();
|
||||
let path_len = path.len();
|
||||
let import_info =
|
||||
ImportInfo { path, container: module, is_trait_assoc_item: false };
|
||||
|
||||
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
|
||||
import_map.collect_trait_assoc_items(
|
||||
db,
|
||||
tr,
|
||||
matches!(item, ItemInNs::Types(_)),
|
||||
&import_info,
|
||||
);
|
||||
}
|
||||
|
||||
match import_map.map.entry(item) {
|
||||
Entry::Vacant(entry) => {
|
||||
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() = import_info;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we've just added a path to a module, descend into it. We might traverse
|
||||
// modules multiple times, but only if the new path to it is shorter than the
|
||||
// first (else we `continue` above).
|
||||
if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
|
||||
worklist.push((mod_id, mk_path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import_map
|
||||
}
|
||||
|
||||
impl PartialEq for ImportMap {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// `fst` and `importables` are built from `map`, so we don't need to compare them.
|
||||
@ -240,6 +249,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
|
||||
fn fst_path(path: &ImportPath) -> String {
|
||||
let _p = profile::span("fst_path");
|
||||
let mut s = path.to_string();
|
||||
s.make_ascii_lowercase();
|
||||
s
|
||||
@ -338,6 +348,7 @@ pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self {
|
||||
}
|
||||
|
||||
fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool {
|
||||
let _p = profile::span("import_map::Query::import_matches");
|
||||
if import.is_trait_assoc_item {
|
||||
if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) {
|
||||
return false;
|
||||
|
@ -141,6 +141,7 @@ fn collect_lang_item<T>(
|
||||
) where
|
||||
T: Into<AttrDefId> + Copy,
|
||||
{
|
||||
let _p = profile::span("collect_lang_item");
|
||||
if let Some(lang_item_name) = lang_attr(db, item) {
|
||||
self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ pub fn take_macros(self) -> Option<MacroDefId> {
|
||||
}
|
||||
|
||||
pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
|
||||
let _p = profile::span("PerNs::filter_visibility");
|
||||
PerNs {
|
||||
types: self.types.filter(|(_, v)| f(*v)),
|
||||
values: self.values.filter(|(_, v)| f(*v)),
|
||||
@ -86,6 +87,7 @@ pub fn or(self, other: PerNs) -> PerNs {
|
||||
}
|
||||
|
||||
pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
|
||||
let _p = profile::span("PerNs::iter_items");
|
||||
self.types
|
||||
.map(|it| ItemInNs::Types(it.0))
|
||||
.into_iter()
|
||||
|
@ -197,6 +197,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
|
||||
}
|
||||
|
||||
pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> {
|
||||
let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));
|
||||
// FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from
|
||||
// that instead?
|
||||
|
||||
@ -321,6 +322,7 @@ fn map_value_to_range(value: u64) -> (usize, usize) {
|
||||
|
||||
impl Query {
|
||||
pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
|
||||
let _p = profile::span("symbol_index::Query::search");
|
||||
let mut op = fst::map::OpBuilder::new();
|
||||
for file_symbols in indices.iter() {
|
||||
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
||||
|
Loading…
Reference in New Issue
Block a user