mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
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:
commit
db6988d4e7
7 changed files with 117 additions and 35 deletions
|
@ -81,32 +81,34 @@ 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_map(|(import_path, definition)| {
|
})
|
||||||
render_resolution_with_import(
|
.filter(|(mod_path, _)| mod_path.len() > 1)
|
||||||
RenderContext::new(ctx),
|
.take(20)
|
||||||
import_path.clone(),
|
.filter_map(|(import_path, definition)| {
|
||||||
import_scope.clone(),
|
render_resolution_with_import(
|
||||||
ctx.config.merge,
|
RenderContext::new(ctx),
|
||||||
&definition,
|
import_path.clone(),
|
||||||
)
|
import_scope.clone(),
|
||||||
})
|
ctx.config.merge,
|
||||||
.take(20);
|
&definition,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
acc.add_all(possible_imports);
|
acc.add_all(possible_imports);
|
||||||
Some(())
|
Some(())
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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,10 +324,17 @@ 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
|
||||||
let item_path = &import_map.map[item].path;
|
.iter()
|
||||||
fst_path(item_path) == fst_path(path)
|
.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 {
|
if query.case_sensitive {
|
||||||
// FIXME: This does not do a subsequence match.
|
// FIXME: This does not do a subsequence match.
|
||||||
|
@ -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#""#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue