6614: Improve autoimports on completion speed r=matklad a=SomeoneToIgnore

Presumably closes https://github.com/rust-analyzer/rust-analyzer/issues/6594
May help https://github.com/rust-analyzer/rust-analyzer/issues/6612

* Ignore modules eaferly
* Do less completion string rendering

6632: Pin cargo_metadata r=matklad a=kjeremy

See: https://github.com/oli-obk/cargo_metadata/pull/142#issuecomment-733653275

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: kjeremy <kjeremy@gmail.com>
This commit is contained in:
bors[bot] 2020-11-26 10:43:35 +00:00 committed by GitHub
commit db6988d4e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 117 additions and 35 deletions

View file

@ -81,22 +81,25 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
let potential_import_name = ctx.token.to_string(); let potential_import_name = ctx.token.to_string();
let possible_imports = let possible_imports = imports_locator::find_similar_imports(
imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, 400) &ctx.sema,
.filter_map(|import_candidate| match import_candidate { ctx.krate?,
// when completing outside the use declaration, modules are pretty useless &potential_import_name,
// and tend to bloat the completion suggestions a lot 50,
Either::Left(ModuleDef::Module(_)) => None, true,
Either::Left(module_def) => Some(( )
current_module.find_use_path(ctx.db, module_def)?, .filter_map(|import_candidate| {
ScopeDef::ModuleDef(module_def), Some(match import_candidate {
)), Either::Left(module_def) => {
Either::Right(macro_def) => Some(( (current_module.find_use_path(ctx.db, module_def)?, ScopeDef::ModuleDef(module_def))
current_module.find_use_path(ctx.db, macro_def)?, }
ScopeDef::MacroDef(macro_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) .filter(|(mod_path, _)| mod_path.len() > 1)
.take(20)
.filter_map(|(import_path, definition)| { .filter_map(|(import_path, definition)| {
render_resolution_with_import( render_resolution_with_import(
RenderContext::new(ctx), RenderContext::new(ctx),
@ -105,8 +108,7 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
ctx.config.merge, ctx.config.merge,
&definition, &definition,
) )
}) });
.take(20);
acc.add_all(possible_imports); acc.add_all(possible_imports);
Some(()) Some(())

View file

@ -150,6 +150,7 @@ impl<'a> Render<'a> {
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
resolution: &ScopeDef, resolution: &ScopeDef,
) -> Option<CompletionItem> { ) -> Option<CompletionItem> {
let _p = profile::span("render_resolution");
use hir::ModuleDef::*; use hir::ModuleDef::*;
let completion_kind = match resolution { let completion_kind = match resolution {

View file

@ -12,7 +12,7 @@ doctest = false
[dependencies] [dependencies]
crossbeam-channel = "0.5.0" crossbeam-channel = "0.5.0"
log = "0.4.8" log = "0.4.8"
cargo_metadata = "0.12.0" cargo_metadata = "=0.12.0"
serde_json = "1.0.48" serde_json = "1.0.48"
jod-thread = "0.1.1" jod-thread = "0.1.1"

View file

@ -7,7 +7,7 @@ use fst::{self, Streamer};
use hir_expand::name::Name; use hir_expand::name::Name;
use indexmap::{map::Entry, IndexMap}; use indexmap::{map::Entry, IndexMap};
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHasher}; use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
use smallvec::SmallVec; use smallvec::SmallVec;
use syntax::SmolStr; use syntax::SmolStr;
@ -225,6 +225,19 @@ fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo))
lhs_str.cmp(&rhs_str) lhs_str.cmp(&rhs_str)
} }
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum ImportKind {
Module,
Function,
Adt,
EnumVariant,
Const,
Static,
Trait,
TypeAlias,
BuiltinType,
}
#[derive(Debug)] #[derive(Debug)]
pub struct Query { pub struct Query {
query: String, query: String,
@ -232,6 +245,7 @@ pub struct Query {
anchor_end: bool, anchor_end: bool,
case_sensitive: bool, case_sensitive: bool,
limit: usize, limit: usize,
exclude_import_kinds: FxHashSet<ImportKind>,
} }
impl Query { impl Query {
@ -242,6 +256,7 @@ impl Query {
anchor_end: false, anchor_end: false,
case_sensitive: false, case_sensitive: false,
limit: usize::max_value(), limit: usize::max_value(),
exclude_import_kinds: FxHashSet::default(),
} }
} }
@ -260,6 +275,12 @@ impl Query {
pub fn case_sensitive(self) -> Self { pub fn case_sensitive(self) -> Self {
Self { case_sensitive: true, ..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`. /// Searches dependencies of `krate` for an importable path matching `query`.
@ -303,9 +324,16 @@ pub fn search_dependencies<'a>(
// Add the items from this `ModPath` group. Those are all subsequent items in // Add the items from this `ModPath` group. Those are all subsequent items in
// `importables` whose paths match `path`. // `importables` whose paths match `path`.
let iter = importables.iter().copied().take_while(|item| { let iter = importables
.iter()
.copied()
.take_while(|item| {
let item_path = &import_map.map[item].path; let item_path = &import_map.map[item].path;
fst_path(item_path) == fst_path(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 { if query.case_sensitive {
@ -341,6 +369,20 @@ pub fn search_dependencies<'a>(
res 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)] #[cfg(test)]
mod tests { mod tests {
use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; use base_db::{fixture::WithFixture, SourceDatabase, Upcast};
@ -758,4 +800,34 @@ mod tests {
"#]], "#]],
); );
} }
#[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#""#]],
);
}
} }

View file

@ -36,8 +36,15 @@ pub fn find_similar_imports<'a>(
krate: Crate, krate: Crate,
name_to_import: &str, name_to_import: &str,
limit: usize, limit: usize,
ignore_modules: bool,
) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
let _p = profile::span("find_similar_imports"); 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( find_imports(
sema, sema,
krate, krate,
@ -46,7 +53,7 @@ pub fn find_similar_imports<'a>(
local_query.limit(limit); local_query.limit(limit);
local_query local_query
}, },
import_map::Query::new(name_to_import).limit(limit), external_query,
) )
} }

View file

@ -20,7 +20,7 @@ proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" }
test_utils = { path = "../test_utils", version = "0.0.0" } test_utils = { path = "../test_utils", version = "0.0.0" }
[dev-dependencies] [dev-dependencies]
cargo_metadata = "0.12.0" cargo_metadata = "=0.12.0"
difference = "2.0.0" difference = "2.0.0"
# used as proc macro test targets # used as proc macro test targets

View file

@ -12,7 +12,7 @@ doctest = false
[dependencies] [dependencies]
log = "0.4.8" log = "0.4.8"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
cargo_metadata = "0.12.0" cargo_metadata = "=0.12.0"
serde = { version = "1.0.106", features = ["derive"] } serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0.48" serde_json = "1.0.48"
anyhow = "1.0.26" anyhow = "1.0.26"