Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/symbol_index.rs')
| -rw-r--r-- | crates/ide-db/src/symbol_index.rs | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index 05c3f360fa..c95b541748 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -218,15 +218,18 @@ pub fn crate_symbols(db: &dyn HirDatabase, krate: Crate) -> Box<[&SymbolIndex<'_ // | Editor | Shortcut | // |---------|-----------| // | VS Code | <kbd>Ctrl+T</kbd> -pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol<'_>> { +pub fn world_symbols(db: &RootDatabase, mut query: Query) -> Vec<FileSymbol<'_>> { let _p = tracing::info_span!("world_symbols", query = ?query.query).entered(); - if query.is_crate_search() { - return search_crates(db, &query); - } - - // If we have a path filter, resolve it to target modules - let indices: Vec<_> = if !query.path_filter.is_empty() { + // Search for crates by name (handles "::" and "::foo" queries) + let indices: Vec<_> = if query.is_crate_search() { + query.only_types = false; + query.libs = true; + vec![SymbolIndex::extern_prelude_symbols(db)] + // If we have a path filter, resolve it to target modules + } else if !query.path_filter.is_empty() { + query.only_types = false; + query.libs = true; let target_modules = resolve_path_to_modules( db, &query.path_filter, @@ -258,13 +261,17 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol<'_>> { crates .par_iter() .for_each_with(db.clone(), |snap, &krate| _ = crate_symbols(snap, krate.into())); - crates.into_iter().flat_map(|krate| Vec::from(crate_symbols(db, krate.into()))).collect() + crates + .into_iter() + .flat_map(|krate| Vec::from(crate_symbols(db, krate.into()))) + .chain(std::iter::once(SymbolIndex::extern_prelude_symbols(db))) + .collect() }; let mut res = vec![]; // Normal search: use FST to match item name - query.search::<()>(&indices, |f| { + query.search::<()>(db, &indices, |f| { res.push(f.clone()); ControlFlow::Continue(()) }); @@ -272,39 +279,6 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol<'_>> { res } -/// Search for crates by name (handles "::" and "::foo" queries) -fn search_crates<'db>(db: &'db RootDatabase, query: &Query) -> Vec<FileSymbol<'db>> { - let mut res = vec![]; - - for krate in Crate::all(db) { - let Some(display_name) = krate.display_name(db) else { continue }; - let crate_name = display_name.crate_name().as_str(); - - // If query is empty (sole "::"), return all crates - // Otherwise, fuzzy match the crate name - let matches = if query.query.is_empty() { - true - } else { - query.mode.check(&query.query, query.case_sensitive, crate_name) - }; - - if matches { - // Get the crate root module's symbol index and find the root module symbol - let root_module = krate.root_module(db); - let index = SymbolIndex::module_symbols(db, root_module); - // Find the module symbol itself (representing the crate) - for symbol in index.symbols.iter() { - if matches!(symbol.def, hir::ModuleDef::Module(m) if m == root_module) { - res.push(symbol.clone()); - break; - } - } - } - } - - res -} - /// Resolve a path filter to the target module(s) it points to. /// Returns the modules whose symbol indices should be searched. /// @@ -452,6 +426,33 @@ impl<'db> SymbolIndex<'db> { module_symbols(db, InternedModuleId::new(db, hir::ModuleId::from(module))) } + + /// The symbol index for all extern prelude crates. + pub fn extern_prelude_symbols(db: &dyn HirDatabase) -> &SymbolIndex<'_> { + #[salsa::tracked(returns(ref))] + fn extern_prelude_symbols<'db>(db: &'db dyn HirDatabase) -> SymbolIndex<'db> { + let _p = tracing::info_span!("extern_prelude_symbols").entered(); + + // We call this without attaching because this runs in parallel, so we need to attach here. + hir::attach_db(db, || { + let mut collector = SymbolCollector::new(db, false); + + for krate in Crate::all(db) { + if krate + .display_name(db) + .is_none_or(|name| name.canonical_name().as_str() == "build-script-build") + { + continue; + } + collector.push_crate_root(krate); + } + + SymbolIndex::new(collector.finish()) + }) + } + + extern_prelude_symbols(db) + } } impl fmt::Debug for SymbolIndex<'_> { @@ -555,6 +556,7 @@ impl Query { /// Search symbols in the given indices. pub(crate) fn search<'db, T>( &self, + db: &'db RootDatabase, indices: &[&'db SymbolIndex<'db>], cb: impl FnMut(&'db FileSymbol<'db>) -> ControlFlow<T>, ) -> Option<T> { @@ -568,7 +570,7 @@ impl Query { for index in indices.iter() { op = op.add(index.map.search(&automaton)); } - self.search_maps(indices, op.union(), cb) + self.search_maps(db, indices, op.union(), cb) } SearchMode::Fuzzy => { let automaton = fst::automaton::Subsequence::new(&self.lowercased); @@ -576,7 +578,7 @@ impl Query { for index in indices.iter() { op = op.add(index.map.search(&automaton)); } - self.search_maps(indices, op.union(), cb) + self.search_maps(db, indices, op.union(), cb) } SearchMode::Prefix => { let automaton = fst::automaton::Str::new(&self.lowercased).starts_with(); @@ -584,13 +586,14 @@ impl Query { for index in indices.iter() { op = op.add(index.map.search(&automaton)); } - self.search_maps(indices, op.union(), cb) + self.search_maps(db, indices, op.union(), cb) } } } fn search_maps<'db, T>( &self, + db: &'db RootDatabase, indices: &[&'db SymbolIndex<'db>], mut stream: fst::map::Union<'_>, mut cb: impl FnMut(&'db FileSymbol<'db>) -> ControlFlow<T>, @@ -598,18 +601,21 @@ impl Query { let ignore_underscore_prefixed = !self.query.starts_with("__"); while let Some((_, indexed_values)) = stream.next() { for &IndexedValue { index, value } in indexed_values { - let symbol_index = &indices[index]; + let symbol_index = indices[index]; let (start, end) = SymbolIndex::map_value_to_range(value); for symbol in &symbol_index.symbols[start..end] { let non_type_for_type_only_query = self.only_types - && !matches!( + && !(matches!( symbol.def, hir::ModuleDef::Adt(..) | hir::ModuleDef::TypeAlias(..) | hir::ModuleDef::BuiltinType(..) | hir::ModuleDef::Trait(..) - ); + ) || matches!( + symbol.def, + hir::ModuleDef::Module(module) if module.is_crate_root(db) + )); if non_type_for_type_only_query || !self.matches_assoc_mode(symbol.is_assoc) { continue; } |