Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/context.rs')
-rw-r--r--crates/ide-completion/src/context.rs60
1 files changed, 55 insertions, 5 deletions
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index f8d403122d..3705e2c73d 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -7,8 +7,8 @@ mod tests;
use std::{iter, ops::ControlFlow};
use hir::{
- HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope,
- Symbol, Type, TypeInfo,
+ HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics,
+ SemanticsScope, Symbol, Type, TypeInfo,
};
use ide_db::{
base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -22,6 +22,7 @@ use syntax::{
};
use crate::{
+ config::AutoImportExclusionType,
context::analysis::{expand_and_analyze, AnalysisResult},
CompletionConfig,
};
@@ -429,7 +430,7 @@ pub(crate) struct CompletionContext<'a> {
pub(crate) sema: Semantics<'a, RootDatabase>,
pub(crate) scope: SemanticsScope<'a>,
pub(crate) db: &'a RootDatabase,
- pub(crate) config: &'a CompletionConfig,
+ pub(crate) config: &'a CompletionConfig<'a>,
pub(crate) position: FilePosition,
/// The token before the cursor, in the original file.
@@ -462,6 +463,17 @@ pub(crate) struct CompletionContext<'a> {
/// Here depth will be 2
pub(crate) depth_from_crate_root: usize,
+ /// Traits whose methods will be excluded from flyimport. Flyimport should not suggest
+ /// importing those traits.
+ ///
+ /// Note the trait *themselves* are not excluded, only their methods are.
+ pub(crate) exclude_flyimport: FxHashMap<ModuleDef, AutoImportExclusionType>,
+ /// Traits whose methods should always be excluded, even when in scope (compare `exclude_flyimport_traits`).
+ /// They will *not* be excluded, however, if they are available as a generic bound.
+ ///
+ /// Note the trait *themselves* are not excluded, only their methods are.
+ pub(crate) exclude_traits: FxHashSet<hir::Trait>,
+
/// Whether and how to complete semicolon for unit-returning functions.
pub(crate) complete_semicolon: CompleteSemicolon,
}
@@ -670,7 +682,7 @@ impl<'a> CompletionContext<'a> {
pub(crate) fn new(
db: &'a RootDatabase,
position @ FilePosition { file_id, offset }: FilePosition,
- config: &'a CompletionConfig,
+ config: &'a CompletionConfig<'a>,
) -> Option<(CompletionContext<'a>, CompletionAnalysis)> {
let _p = tracing::info_span!("CompletionContext::new").entered();
let sema = Semantics::new(db);
@@ -742,17 +754,53 @@ impl<'a> CompletionContext<'a> {
let mut locals = FxHashMap::default();
scope.process_all_names(&mut |name, scope| {
if let ScopeDef::Local(local) = scope {
+ // synthetic names currently leak out as we lack synthetic hygiene, so filter them
+ // out here
+ if name.as_str().starts_with('<') {
+ return;
+ }
locals.insert(name, local);
}
});
let depth_from_crate_root = iter::successors(Some(module), |m| m.parent(db))
- // `BlockExpr` modules are not count as module depth
+ // `BlockExpr` modules do not count towards module depth
.filter(|m| !matches!(m.definition_source(db).value, ModuleSource::BlockExpr(_)))
.count()
// exclude `m` itself
.saturating_sub(1);
+ let exclude_traits: FxHashSet<_> = config
+ .exclude_traits
+ .iter()
+ .filter_map(|path| {
+ scope
+ .resolve_mod_path(&ModPath::from_segments(
+ hir::PathKind::Plain,
+ path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
+ ))
+ .find_map(|it| match it {
+ hir::ItemInNs::Types(ModuleDef::Trait(t)) => Some(t),
+ _ => None,
+ })
+ })
+ .collect();
+
+ let mut exclude_flyimport: FxHashMap<_, _> = config
+ .exclude_flyimport
+ .iter()
+ .flat_map(|(path, kind)| {
+ scope
+ .resolve_mod_path(&ModPath::from_segments(
+ hir::PathKind::Plain,
+ path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
+ ))
+ .map(|it| (it.into_module_def(), *kind))
+ })
+ .collect();
+ exclude_flyimport
+ .extend(exclude_traits.iter().map(|&t| (t.into(), AutoImportExclusionType::Always)));
+
let complete_semicolon = if config.add_semicolon_to_unit {
let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| {
match_ast! {
@@ -817,6 +865,8 @@ impl<'a> CompletionContext<'a> {
qualifier_ctx,
locals,
depth_from_crate_root,
+ exclude_flyimport,
+ exclude_traits,
complete_semicolon,
};
Some((ctx, analysis))