let potential_import_name = ctx.token.to_string();
- let possible_imports =
- imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, 400)
- .filter_map(|import_candidate| match import_candidate {
- // when completing outside the use declaration, modules are pretty useless
- // and tend to bloat the completion suggestions a lot
- Either::Left(ModuleDef::Module(_)) => None,
- Either::Left(module_def) => Some((
- current_module.find_use_path(ctx.db, module_def)?,
- ScopeDef::ModuleDef(module_def),
- )),
- Either::Right(macro_def) => Some((
- current_module.find_use_path(ctx.db, macro_def)?,
- ScopeDef::MacroDef(macro_def),
- )),
- })
- .filter(|(mod_path, _)| mod_path.len() > 1)
- .filter_map(|(import_path, definition)| {
- render_resolution_with_import(
- RenderContext::new(ctx),
- import_path.clone(),
- import_scope.clone(),
- ctx.config.merge,
- &definition,
- )
- })
- .take(20);
+ let possible_imports = imports_locator::find_similar_imports(
+ &ctx.sema,
+ ctx.krate?,
+ &potential_import_name,
+ 50,
+ true,
+ )
+ .filter_map(|import_candidate| {
+ Some(match import_candidate {
+ Either::Left(module_def) => {
+ (current_module.find_use_path(ctx.db, module_def)?, ScopeDef::ModuleDef(module_def))
+ }
+ Either::Right(macro_def) => {
+ (current_module.find_use_path(ctx.db, macro_def)?, ScopeDef::MacroDef(macro_def))
+ }
+ })
+ })
+ .filter(|(mod_path, _)| mod_path.len() > 1)
+ .take(20)
+ .filter_map(|(import_path, definition)| {
+ render_resolution_with_import(
+ RenderContext::new(ctx),
+ import_path.clone(),
+ import_scope.clone(),
+ ctx.config.merge,
+ &definition,
+ )
+ });
acc.add_all(possible_imports);
Some(())
use hir_expand::name::Name;
use indexmap::{map::Entry, IndexMap};
use itertools::Itertools;
-use rustc_hash::{FxHashMap, FxHasher};
+use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
use smallvec::SmallVec;
use syntax::SmolStr;
lhs_str.cmp(&rhs_str)
}
+#[derive(Debug, Eq, PartialEq, Hash)]
+pub enum ImportKind {
+ Module,
+ Function,
+ Adt,
+ EnumVariant,
+ Const,
+ Static,
+ Trait,
+ TypeAlias,
+ BuiltinType,
+}
+
#[derive(Debug)]
pub struct Query {
query: String,
anchor_end: bool,
case_sensitive: bool,
limit: usize,
+ exclude_import_kinds: FxHashSet<ImportKind>,
}
impl Query {
anchor_end: false,
case_sensitive: false,
limit: usize::max_value(),
+ exclude_import_kinds: FxHashSet::default(),
}
}
pub fn case_sensitive(self) -> Self {
Self { case_sensitive: true, ..self }
}
+
+ /// Do not include imports of the specified kind in the search results.
+ pub fn exclude_import_kind(mut self, import_kind: ImportKind) -> Self {
+ self.exclude_import_kinds.insert(import_kind);
+ self
+ }
}
/// Searches dependencies of `krate` for an importable path matching `query`.
// Add the items from this `ModPath` group. Those are all subsequent items in
// `importables` whose paths match `path`.
- let iter = importables.iter().copied().take_while(|item| {
- let item_path = &import_map.map[item].path;
- fst_path(item_path) == fst_path(path)
- });
+ let iter = importables
+ .iter()
+ .copied()
+ .take_while(|item| {
+ let item_path = &import_map.map[item].path;
+ fst_path(item_path) == fst_path(path)
+ })
+ .filter(|&item| match item_import_kind(item) {
+ Some(import_kind) => !query.exclude_import_kinds.contains(&import_kind),
+ None => true,
+ });
if query.case_sensitive {
// FIXME: This does not do a subsequence match.
res
}
+fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
+ Some(match item.as_module_def_id()? {
+ ModuleDefId::ModuleId(_) => ImportKind::Module,
+ ModuleDefId::FunctionId(_) => ImportKind::Function,
+ ModuleDefId::AdtId(_) => ImportKind::Adt,
+ ModuleDefId::EnumVariantId(_) => ImportKind::EnumVariant,
+ ModuleDefId::ConstId(_) => ImportKind::Const,
+ ModuleDefId::StaticId(_) => ImportKind::Static,
+ ModuleDefId::TraitId(_) => ImportKind::Trait,
+ ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias,
+ ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType,
+ })
+}
+
#[cfg(test)]
mod tests {
use base_db::{fixture::WithFixture, SourceDatabase, Upcast};
"#]],
);
}
+
+ #[test]
+ fn search_exclusions() {
+ let ra_fixture = r#"
+ //- /main.rs crate:main deps:dep
+ //- /dep.rs crate:dep
+
+ pub struct fmt;
+ pub struct FMT;
+ "#;
+
+ check_search(
+ ra_fixture,
+ "main",
+ Query::new("FMT"),
+ expect![[r#"
+ dep::fmt (t)
+ dep::fmt (v)
+ dep::FMT (t)
+ dep::FMT (v)
+ "#]],
+ );
+
+ check_search(
+ ra_fixture,
+ "main",
+ Query::new("FMT").exclude_import_kind(ImportKind::Adt),
+ expect![[r#""#]],
+ );
+ }
}