]> git.lizzy.rs Git - rust.git/commitdiff
Improve autoimports on completion speed
authorKirill Bulatov <mail4score@gmail.com>
Tue, 24 Nov 2020 00:26:16 +0000 (02:26 +0200)
committerKirill Bulatov <mail4score@gmail.com>
Tue, 24 Nov 2020 00:28:45 +0000 (02:28 +0200)
* Ignore modules eaferly
* Do less completion string rendering

crates/completion/src/completions/unqualified_path.rs
crates/completion/src/render.rs
crates/hir_def/src/import_map.rs
crates/ide_db/src/imports_locator.rs

index 86c143b637f713bfbee8e25c574b1108947a26db..f452c98e4e8c66956c161c82f20008210c0932aa 100644 (file)
@@ -79,32 +79,34 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
 
     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(())
index e892d4de8590a6c76d00f452a4ff5baa11e3b737..bce02f5773888a2a5df2ded5e6785aaf0c30a6a5 100644 (file)
@@ -150,6 +150,7 @@ fn render_resolution(
         import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
         resolution: &ScopeDef,
     ) -> Option<CompletionItem> {
+        let _p = profile::span("render_resolution");
         use hir::ModuleDef::*;
 
         let completion_kind = match resolution {
index 1e24f29a81f4a400b36e69f9343ab7edd1761776..c0f10884808e6516148f858bd0934c3c026a269d 100644 (file)
@@ -7,7 +7,7 @@
 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;
 
@@ -225,6 +225,19 @@ fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo))
     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,
@@ -232,6 +245,7 @@ pub struct Query {
     anchor_end: bool,
     case_sensitive: bool,
     limit: usize,
+    exclude_import_kinds: FxHashSet<ImportKind>,
 }
 
 impl Query {
@@ -242,6 +256,7 @@ pub fn new(query: &str) -> Self {
             anchor_end: false,
             case_sensitive: false,
             limit: usize::max_value(),
+            exclude_import_kinds: FxHashSet::default(),
         }
     }
 
@@ -260,6 +275,12 @@ pub fn limit(self, limit: usize) -> Self {
     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`.
@@ -303,10 +324,17 @@ pub fn search_dependencies<'a>(
 
             // 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.
@@ -341,6 +369,20 @@ pub fn search_dependencies<'a>(
     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};
@@ -758,4 +800,34 @@ pub fn no() {}
             "#]],
         );
     }
+
+    #[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#""#]],
+        );
+    }
 }
index 9d8ea7368d3a5141ae14dff7d03f18b45917e3a7..09046d3c36a8dad72bfd1cf3bc7d8cad9d8071c4 100644 (file)
@@ -36,8 +36,15 @@ pub fn find_similar_imports<'a>(
     krate: Crate,
     name_to_import: &str,
     limit: usize,
+    ignore_modules: bool,
 ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
     let _p = profile::span("find_similar_imports");
+
+    let mut external_query = import_map::Query::new(name_to_import).limit(limit);
+    if ignore_modules {
+        external_query = external_query.exclude_import_kind(import_map::ImportKind::Module);
+    }
+
     find_imports(
         sema,
         krate,
@@ -46,7 +53,7 @@ pub fn find_similar_imports<'a>(
             local_query.limit(limit);
             local_query
         },
-        import_map::Query::new(name_to_import).limit(limit),
+        external_query,
     )
 }