//! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
//! capability enabled.
-use hir::{AsAssocItem, ModPath, ScopeDef};
+use hir::{AsAssocItem, ItemInNs, ModPath, ScopeDef};
use ide_db::helpers::{
import_assets::{ImportAssets, ImportCandidate},
insert_use::ImportScope,
};
-use rustc_hash::FxHashSet;
use syntax::{AstNode, SyntaxNode, T};
use crate::{
&ctx.sema,
)?;
- let scope_definitions = scope_definitions(ctx);
let mut all_mod_paths = import_assets
.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
.into_iter()
.map(|import| {
let proposed_def = match import.item_to_display() {
- hir::ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()),
- hir::ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
- hir::ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
+ ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()),
+ ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
+ ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
};
(import, proposed_def)
})
- .filter(|(_, proposed_def)| !scope_definitions.contains(proposed_def))
.collect::<Vec<_>>();
all_mod_paths.sort_by_cached_key(|(import, _)| {
compute_fuzzy_completion_order_key(import.display_path(), &user_input_lowercased)
Some(())
}
-fn scope_definitions(ctx: &CompletionContext) -> FxHashSet<ScopeDef> {
- let mut scope_definitions = FxHashSet::default();
- ctx.scope.process_all_names(&mut |_, scope_def| {
- scope_definitions.insert(scope_def);
- });
- scope_definitions
-}
-
pub(crate) fn position_for_import<'a>(
ctx: &'a CompletionContext,
import_candidate: Option<&ImportCandidate>,
})
}
-fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
+fn import_assets<'a>(ctx: &'a CompletionContext, fuzzy_name: String) -> Option<ImportAssets<'a>> {
let current_module = ctx.scope.module()?;
if let Some(dot_receiver) = &ctx.dot_receiver {
ImportAssets::for_fuzzy_method_call(
current_module,
ctx.sema.type_of_expr(dot_receiver)?,
fuzzy_name,
+ ctx.scope.clone(),
)
} else {
let fuzzy_name_length = fuzzy_name.len();
ctx.path_qual.clone(),
fuzzy_name,
&ctx.sema,
+ ctx.scope.clone(),
)?;
if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_))
use either::Either;
use hir::{
AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
- ModuleDef, PathResolution, PrefixKind, Semantics, Type,
+ ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type,
};
use rustc_hash::FxHashSet;
use syntax::{ast, AstNode};
}
#[derive(Debug)]
-pub struct ImportAssets {
+pub struct ImportAssets<'a> {
import_candidate: ImportCandidate,
module_with_candidate: Module,
+ scope: SemanticsScope<'a>,
}
-impl ImportAssets {
+impl<'a> ImportAssets<'a> {
pub fn for_method_call(
method_call: &ast::MethodCallExpr,
- sema: &Semantics<RootDatabase>,
+ sema: &'a Semantics<RootDatabase>,
) -> Option<Self> {
+ let scope = sema.scope(method_call.syntax());
Some(Self {
import_candidate: ImportCandidate::for_method_call(sema, method_call)?,
- module_with_candidate: sema.scope(method_call.syntax()).module()?,
+ module_with_candidate: scope.module()?,
+ scope,
})
}
pub fn for_exact_path(
fully_qualified_path: &ast::Path,
- sema: &Semantics<RootDatabase>,
+ sema: &'a Semantics<RootDatabase>,
) -> Option<Self> {
let syntax_under_caret = fully_qualified_path.syntax();
if syntax_under_caret.ancestors().find_map(ast::Use::cast).is_some() {
return None;
}
+ let scope = sema.scope(syntax_under_caret);
Some(Self {
import_candidate: ImportCandidate::for_regular_path(sema, fully_qualified_path)?,
- module_with_candidate: sema.scope(syntax_under_caret).module()?,
+ module_with_candidate: scope.module()?,
+ scope,
})
}
qualifier: Option<ast::Path>,
fuzzy_name: String,
sema: &Semantics<RootDatabase>,
+ scope: SemanticsScope<'a>,
) -> Option<Self> {
Some(Self {
import_candidate: ImportCandidate::for_fuzzy_path(qualifier, fuzzy_name, sema)?,
module_with_candidate,
+ scope,
})
}
module_with_method_call: Module,
receiver_ty: Type,
fuzzy_method_name: String,
+ scope: SemanticsScope<'a>,
) -> Option<Self> {
Some(Self {
import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate {
name: NameToImport::Fuzzy(fuzzy_method_name),
}),
module_with_candidate: module_with_method_call,
+ scope,
})
}
}
}
}
-impl ImportAssets {
+impl<'a> ImportAssets<'a> {
pub fn import_candidate(&self) -> &ImportCandidate {
&self.import_candidate
}
prefixed: Option<PrefixKind>,
) -> Vec<LocatedImport> {
let current_crate = self.module_with_candidate.krate();
+ let scope_definitions = self.scope_definitions();
let imports_for_candidate_name = match self.name_to_import() {
NameToImport::Exact(exact_name) => {
self.applicable_defs(sema.db, prefixed, imports_for_candidate_name)
.into_iter()
.filter(|import| import.import_path().len() > 1)
+ .filter(|import| {
+ let proposed_def = match import.item_to_import() {
+ ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()),
+ ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()),
+ ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()),
+ };
+ !scope_definitions.contains(&proposed_def)
+ })
.collect()
}
+ fn scope_definitions(&self) -> FxHashSet<ScopeDef> {
+ let mut scope_definitions = FxHashSet::default();
+ self.scope.process_all_names(&mut |_, scope_def| {
+ scope_definitions.insert(scope_def);
+ });
+ scope_definitions
+ }
+
fn applicable_defs(
&self,
db: &RootDatabase,
Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => (first_segment, qualifier),
};
- // TODO kb zz.syntax().ast_node() <- two options are now proposed despite the trait being imported
let unresolved_qualifier_string = unresolved_qualifier.to_string();
let unresolved_first_segment_string = unresolved_first_segment.to_string();