fix: Complete functions and methods from block level impls
This commit is contained in:
parent
dbd5a70ea3
commit
d7a544e69a
@ -2787,6 +2787,7 @@ pub fn iterate_method_candidates<T>(
|
|||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
|
with_local_impls: Option<Module>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: impl FnMut(Type, Function) -> Option<T>,
|
mut callback: impl FnMut(Type, Function) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
@ -2797,6 +2798,7 @@ pub fn iterate_method_candidates<T>(
|
|||||||
db,
|
db,
|
||||||
krate,
|
krate,
|
||||||
traits_in_scope,
|
traits_in_scope,
|
||||||
|
with_local_impls,
|
||||||
name,
|
name,
|
||||||
&mut |ty, assoc_item_id| {
|
&mut |ty, assoc_item_id| {
|
||||||
if let AssocItemId::FunctionId(func) = assoc_item_id {
|
if let AssocItemId::FunctionId(func) = assoc_item_id {
|
||||||
@ -2816,6 +2818,7 @@ fn iterate_method_candidates_dyn(
|
|||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
|
with_local_impls: Option<Module>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
||||||
) {
|
) {
|
||||||
@ -2831,7 +2834,7 @@ fn iterate_method_candidates_dyn(
|
|||||||
env,
|
env,
|
||||||
krate,
|
krate,
|
||||||
traits_in_scope,
|
traits_in_scope,
|
||||||
None,
|
with_local_impls.and_then(|b| b.id.containing_block()).into(),
|
||||||
name,
|
name,
|
||||||
method_resolution::LookupMode::MethodCall,
|
method_resolution::LookupMode::MethodCall,
|
||||||
&mut |ty, id| callback(&ty.value, id),
|
&mut |ty, id| callback(&ty.value, id),
|
||||||
@ -2843,6 +2846,7 @@ pub fn iterate_path_candidates<T>(
|
|||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
|
with_local_impls: Option<Module>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: impl FnMut(Type, AssocItem) -> Option<T>,
|
mut callback: impl FnMut(Type, AssocItem) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
@ -2852,6 +2856,7 @@ pub fn iterate_path_candidates<T>(
|
|||||||
db,
|
db,
|
||||||
krate,
|
krate,
|
||||||
traits_in_scope,
|
traits_in_scope,
|
||||||
|
with_local_impls,
|
||||||
name,
|
name,
|
||||||
&mut |ty, assoc_item_id| {
|
&mut |ty, assoc_item_id| {
|
||||||
if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) {
|
if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) {
|
||||||
@ -2869,6 +2874,7 @@ fn iterate_path_candidates_dyn(
|
|||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
|
with_local_impls: Option<Module>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
||||||
) {
|
) {
|
||||||
@ -2883,7 +2889,7 @@ fn iterate_path_candidates_dyn(
|
|||||||
env,
|
env,
|
||||||
krate,
|
krate,
|
||||||
traits_in_scope,
|
traits_in_scope,
|
||||||
None,
|
with_local_impls.and_then(|b| b.id.containing_block()).into(),
|
||||||
name,
|
name,
|
||||||
method_resolution::LookupMode::Path,
|
method_resolution::LookupMode::Path,
|
||||||
&mut |ty, id| callback(&ty.value, id),
|
&mut |ty, id| callback(&ty.value, id),
|
||||||
|
@ -996,7 +996,7 @@ fn infer_method_call(
|
|||||||
self.trait_env.clone(),
|
self.trait_env.clone(),
|
||||||
krate,
|
krate,
|
||||||
&traits_in_scope,
|
&traits_in_scope,
|
||||||
self.resolver.module(),
|
self.resolver.module().into(),
|
||||||
method_name,
|
method_name,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -227,7 +227,7 @@ fn resolve_ty_assoc_item(
|
|||||||
self.table.trait_env.clone(),
|
self.table.trait_env.clone(),
|
||||||
krate,
|
krate,
|
||||||
&traits_in_scope,
|
&traits_in_scope,
|
||||||
self.resolver.module(),
|
self.resolver.module().into(),
|
||||||
Some(name),
|
Some(name),
|
||||||
method_resolution::LookupMode::Path,
|
method_resolution::LookupMode::Path,
|
||||||
move |_ty, item| {
|
move |_ty, item| {
|
||||||
|
@ -437,7 +437,7 @@ pub(crate) fn lookup_method(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<(Canonical<Ty>, FunctionId)> {
|
) -> Option<(Canonical<Ty>, FunctionId)> {
|
||||||
iterate_method_candidates(
|
iterate_method_candidates(
|
||||||
@ -468,6 +468,34 @@ pub enum LookupMode {
|
|||||||
Path,
|
Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum VisibleFromModule {
|
||||||
|
/// Filter for results that are visible from the given module
|
||||||
|
Filter(ModuleId),
|
||||||
|
/// Include impls from the given block.
|
||||||
|
IncludeBlock(BlockId),
|
||||||
|
/// Do nothing special in regards visibility
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<ModuleId>> for VisibleFromModule {
|
||||||
|
fn from(module: Option<ModuleId>) -> Self {
|
||||||
|
match module {
|
||||||
|
Some(module) => Self::Filter(module),
|
||||||
|
None => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<BlockId>> for VisibleFromModule {
|
||||||
|
fn from(block: Option<BlockId>) -> Self {
|
||||||
|
match block {
|
||||||
|
Some(block) => Self::IncludeBlock(block),
|
||||||
|
None => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This would be nicer if it just returned an iterator, but that runs into
|
// This would be nicer if it just returned an iterator, but that runs into
|
||||||
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
|
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
|
||||||
// FIXME add a context type here?
|
// FIXME add a context type here?
|
||||||
@ -477,7 +505,7 @@ pub fn iterate_method_candidates<T>(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mode: LookupMode,
|
mode: LookupMode,
|
||||||
mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
|
mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
|
||||||
@ -510,7 +538,7 @@ pub fn iterate_method_candidates_dyn(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mode: LookupMode,
|
mode: LookupMode,
|
||||||
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
@ -578,7 +606,7 @@ fn iterate_method_candidates_with_autoref(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
@ -644,7 +672,7 @@ fn iterate_method_candidates_by_receiver(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
@ -686,7 +714,7 @@ fn iterate_method_candidates_for_self_ty(
|
|||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
@ -797,7 +825,7 @@ fn iterate_inherent_methods(
|
|||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
receiver_ty: Option<&Canonical<Ty>>,
|
receiver_ty: Option<&Canonical<Ty>>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: VisibleFromModule,
|
||||||
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
let def_crates = match def_crates(db, &self_ty.value, krate) {
|
let def_crates = match def_crates(db, &self_ty.value, krate) {
|
||||||
@ -805,8 +833,13 @@ fn iterate_inherent_methods(
|
|||||||
None => return ControlFlow::Continue(()),
|
None => return ControlFlow::Continue(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(module_id) = visible_from_module {
|
let (module, block) = match visible_from_module {
|
||||||
if let Some(block_id) = module_id.containing_block() {
|
VisibleFromModule::Filter(module) => (Some(module), module.containing_block()),
|
||||||
|
VisibleFromModule::IncludeBlock(block) => (None, Some(block)),
|
||||||
|
VisibleFromModule::None => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(block_id) = block {
|
||||||
if let Some(impls) = db.inherent_impls_in_block(block_id) {
|
if let Some(impls) = db.inherent_impls_in_block(block_id) {
|
||||||
impls_for_self_ty(
|
impls_for_self_ty(
|
||||||
&impls,
|
&impls,
|
||||||
@ -815,25 +848,15 @@ fn iterate_inherent_methods(
|
|||||||
env.clone(),
|
env.clone(),
|
||||||
name,
|
name,
|
||||||
receiver_ty,
|
receiver_ty,
|
||||||
visible_from_module,
|
module,
|
||||||
callback,
|
callback,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for krate in def_crates {
|
for krate in def_crates {
|
||||||
let impls = db.inherent_impls_in_crate(krate);
|
let impls = db.inherent_impls_in_crate(krate);
|
||||||
impls_for_self_ty(
|
impls_for_self_ty(&impls, self_ty, db, env.clone(), name, receiver_ty, module, callback)?;
|
||||||
&impls,
|
|
||||||
self_ty,
|
|
||||||
db,
|
|
||||||
env.clone(),
|
|
||||||
name,
|
|
||||||
receiver_ty,
|
|
||||||
visible_from_module,
|
|
||||||
callback,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
return ControlFlow::Continue(());
|
return ControlFlow::Continue(());
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ fn is_ref_and_impls_iter_method(
|
|||||||
sema.db,
|
sema.db,
|
||||||
krate,
|
krate,
|
||||||
&traits_in_scope,
|
&traits_in_scope,
|
||||||
|
None,
|
||||||
Some(&wanted_method),
|
Some(&wanted_method),
|
||||||
|_, func| {
|
|_, func| {
|
||||||
if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
|
if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
|
||||||
|
@ -93,7 +93,9 @@ fn get_impl_method(
|
|||||||
let krate = impl_def.module(db).krate();
|
let krate = impl_def.module(db).krate();
|
||||||
let ty = impl_def.self_ty(db);
|
let ty = impl_def.self_ty(db);
|
||||||
let traits_in_scope = scope.visible_traits();
|
let traits_in_scope = scope.visible_traits();
|
||||||
ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func))
|
ty.iterate_method_candidates(db, krate, &traits_in_scope, None, Some(fn_name), |_, func| {
|
||||||
|
Some(func)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -253,7 +253,7 @@ fn enum_variants_with_paths(
|
|||||||
) {
|
) {
|
||||||
let variants = enum_.variants(ctx.db);
|
let variants = enum_.variants(ctx.db);
|
||||||
|
|
||||||
let module = if let Some(module) = ctx.scope.module() {
|
let module = if let Some(module) = ctx.module {
|
||||||
// Compute path from the completion site if available.
|
// Compute path from the completion site if available.
|
||||||
module
|
module
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,7 +80,7 @@ fn flyimport_derive(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let potential_import_name = ctx.token.to_string();
|
let potential_import_name = ctx.token.to_string();
|
||||||
let module = ctx.scope.module()?;
|
let module = ctx.module?;
|
||||||
let parent = ctx.token.parent()?;
|
let parent = ctx.token.parent()?;
|
||||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||||
let import_assets = ImportAssets::for_fuzzy_path(
|
let import_assets = ImportAssets::for_fuzzy_path(
|
||||||
|
@ -84,12 +84,19 @@ fn complete_methods(
|
|||||||
traits_in_scope.remove(&drop_trait.into());
|
traits_in_scope.remove(&drop_trait.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
|
receiver.iterate_method_candidates(
|
||||||
|
ctx.db,
|
||||||
|
krate,
|
||||||
|
&traits_in_scope,
|
||||||
|
ctx.module,
|
||||||
|
None,
|
||||||
|
|_ty, func| {
|
||||||
if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
|
if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
|
||||||
f(func);
|
f(func);
|
||||||
}
|
}
|
||||||
None::<()>
|
None::<()>
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,6 +272,37 @@ fn foo(a: lib::A) { a.$0 }
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_local_impls() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs crate:lib
|
||||||
|
pub struct A {}
|
||||||
|
mod m {
|
||||||
|
impl super::A {
|
||||||
|
pub fn pub_module_method(&self) {}
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
impl super::A {
|
||||||
|
pub fn pub_foreign_local_method(&self) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//- /main.rs crate:main deps:lib
|
||||||
|
fn foo(a: lib::A) {
|
||||||
|
impl lib::A {
|
||||||
|
fn local_method(&self) {}
|
||||||
|
}
|
||||||
|
a.$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
me local_method() fn(&self)
|
||||||
|
me pub_module_method() fn(&self)
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_doc_hidden_filtering() {
|
fn test_doc_hidden_filtering() {
|
||||||
check(
|
check(
|
||||||
|
@ -217,7 +217,7 @@ pub(crate) fn position_for_import(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
|
fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
|
||||||
let current_module = ctx.scope.module()?;
|
let current_module = ctx.module?;
|
||||||
if let Some(dot_receiver) = ctx.dot_receiver() {
|
if let Some(dot_receiver) = ctx.dot_receiver() {
|
||||||
ImportAssets::for_fuzzy_method_call(
|
ImportAssets::for_fuzzy_method_call(
|
||||||
current_module,
|
current_module,
|
||||||
|
@ -22,7 +22,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
|
|||||||
|
|
||||||
let _p = profile::span("completion::complete_mod");
|
let _p = profile::span("completion::complete_mod");
|
||||||
|
|
||||||
let current_module = ctx.scope.module()?;
|
let current_module = ctx.module?;
|
||||||
|
|
||||||
let module_definition_file =
|
let module_definition_file =
|
||||||
current_module.definition_source(ctx.db).file_id.original_file(ctx.db);
|
current_module.definition_source(ctx.db).file_id.original_file(ctx.db);
|
||||||
|
@ -51,7 +51,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let context_module = ctx.scope.module();
|
let context_module = ctx.module;
|
||||||
|
|
||||||
match ctx.completion_location {
|
match ctx.completion_location {
|
||||||
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
|
||||||
@ -75,7 +75,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||||||
match kind {
|
match kind {
|
||||||
Some(PathKind::Vis { .. }) => {
|
Some(PathKind::Vis { .. }) => {
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
|
||||||
if let Some(current_module) = ctx.scope.module() {
|
if let Some(current_module) = ctx.module {
|
||||||
if let Some(next) = current_module
|
if let Some(next) = current_module
|
||||||
.path_to_root(ctx.db)
|
.path_to_root(ctx.db)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -189,7 +189,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
hir::ModuleDef::BuiltinType(builtin) => {
|
hir::ModuleDef::BuiltinType(builtin) => {
|
||||||
let module = match ctx.scope.module() {
|
let module = match ctx.module {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
@ -205,10 +205,17 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||||||
let krate = ctx.krate;
|
let krate = ctx.krate;
|
||||||
if let Some(krate) = krate {
|
if let Some(krate) = krate {
|
||||||
let traits_in_scope = ctx.scope.visible_traits();
|
let traits_in_scope = ctx.scope.visible_traits();
|
||||||
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
|
ty.iterate_path_candidates(
|
||||||
|
ctx.db,
|
||||||
|
krate,
|
||||||
|
&traits_in_scope,
|
||||||
|
ctx.module,
|
||||||
|
None,
|
||||||
|
|_ty, item| {
|
||||||
add_assoc_item(acc, ctx, item);
|
add_assoc_item(acc, ctx, item);
|
||||||
None::<()>
|
None::<()>
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Iterate assoc types separately
|
// Iterate assoc types separately
|
||||||
ty.iterate_assoc_items(ctx.db, krate, |item| {
|
ty.iterate_assoc_items(ctx.db, krate, |item| {
|
||||||
@ -239,14 +246,21 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
|||||||
|
|
||||||
let traits_in_scope = ctx.scope.visible_traits();
|
let traits_in_scope = ctx.scope.visible_traits();
|
||||||
let mut seen = FxHashSet::default();
|
let mut seen = FxHashSet::default();
|
||||||
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
|
ty.iterate_path_candidates(
|
||||||
|
ctx.db,
|
||||||
|
krate,
|
||||||
|
&traits_in_scope,
|
||||||
|
ctx.module,
|
||||||
|
None,
|
||||||
|
|_ty, item| {
|
||||||
// We might iterate candidates of a trait multiple times here, so deduplicate
|
// We might iterate candidates of a trait multiple times here, so deduplicate
|
||||||
// them.
|
// them.
|
||||||
if seen.insert(item) {
|
if seen.insert(item) {
|
||||||
add_assoc_item(acc, ctx, item);
|
add_assoc_item(acc, ctx, item);
|
||||||
}
|
}
|
||||||
None::<()>
|
None::<()>
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
|
hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
|
||||||
|
@ -59,8 +59,7 @@ pub(crate) fn complete_record_literal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
|
if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
|
||||||
let module =
|
let module = if let Some(module) = ctx.module { module } else { strukt.module(ctx.db) };
|
||||||
if let Some(module) = ctx.scope.module() { module } else { strukt.module(ctx.db) };
|
|
||||||
|
|
||||||
let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt));
|
let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt));
|
||||||
|
|
||||||
|
@ -103,6 +103,8 @@ pub(crate) struct CompletionContext<'a> {
|
|||||||
pub(super) token: SyntaxToken,
|
pub(super) token: SyntaxToken,
|
||||||
/// The crate of the current file.
|
/// The crate of the current file.
|
||||||
pub(super) krate: Option<hir::Crate>,
|
pub(super) krate: Option<hir::Crate>,
|
||||||
|
/// The crate of the `scope`.
|
||||||
|
pub(super) module: Option<hir::Module>,
|
||||||
pub(super) expected_name: Option<NameOrNameRef>,
|
pub(super) expected_name: Option<NameOrNameRef>,
|
||||||
pub(super) expected_type: Option<Type>,
|
pub(super) expected_type: Option<Type>,
|
||||||
|
|
||||||
@ -338,7 +340,7 @@ fn is_visible_impl(
|
|||||||
attrs: &hir::Attrs,
|
attrs: &hir::Attrs,
|
||||||
defining_crate: hir::Crate,
|
defining_crate: hir::Crate,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let module = match self.scope.module() {
|
let module = match self.module {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
@ -394,6 +396,7 @@ pub(super) fn new(
|
|||||||
let token = sema.descend_into_macros_single(original_token.clone());
|
let token = sema.descend_into_macros_single(original_token.clone());
|
||||||
let scope = sema.scope_at_offset(&token.parent()?, offset);
|
let scope = sema.scope_at_offset(&token.parent()?, offset);
|
||||||
let krate = scope.krate();
|
let krate = scope.krate();
|
||||||
|
let module = scope.module();
|
||||||
let mut locals = vec![];
|
let mut locals = vec![];
|
||||||
scope.process_all_names(&mut |name, scope| {
|
scope.process_all_names(&mut |name, scope| {
|
||||||
if let ScopeDef::Local(local) = scope {
|
if let ScopeDef::Local(local) = scope {
|
||||||
@ -410,6 +413,7 @@ pub(super) fn new(
|
|||||||
original_token,
|
original_token,
|
||||||
token,
|
token,
|
||||||
krate,
|
krate,
|
||||||
|
module,
|
||||||
expected_name: None,
|
expected_name: None,
|
||||||
expected_type: None,
|
expected_type: None,
|
||||||
function_def: None,
|
function_def: None,
|
||||||
|
@ -144,7 +144,7 @@ fn visible_fields(
|
|||||||
fields: &[hir::Field],
|
fields: &[hir::Field],
|
||||||
item: impl HasAttrs,
|
item: impl HasAttrs,
|
||||||
) -> Option<(Vec<hir::Field>, bool)> {
|
) -> Option<(Vec<hir::Field>, bool)> {
|
||||||
let module = ctx.completion.scope.module()?;
|
let module = ctx.completion.module?;
|
||||||
let n_fields = fields.len();
|
let n_fields = fields.len();
|
||||||
let fields = fields
|
let fields = fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -119,7 +119,7 @@ fn visible_fields(
|
|||||||
fields: &[hir::Field],
|
fields: &[hir::Field],
|
||||||
item: impl HasAttrs,
|
item: impl HasAttrs,
|
||||||
) -> Option<(Vec<hir::Field>, bool)> {
|
) -> Option<(Vec<hir::Field>, bool)> {
|
||||||
let module = ctx.completion.scope.module()?;
|
let module = ctx.completion.module?;
|
||||||
let n_fields = fields.len();
|
let n_fields = fields.len();
|
||||||
let fields = fields
|
let fields = fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -185,11 +185,8 @@ fn import_edits(
|
|||||||
hir::PathResolution::Def(def) => def.into(),
|
hir::PathResolution::Def(def) => def.into(),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let path = ctx.scope.module()?.find_use_path_prefixed(
|
let path =
|
||||||
ctx.db,
|
ctx.module?.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?;
|
||||||
item,
|
|
||||||
ctx.config.insert_use.prefix_kind,
|
|
||||||
)?;
|
|
||||||
Some((path.len() > 1).then(|| ImportEdit {
|
Some((path.len() > 1).then(|| ImportEdit {
|
||||||
import: LocatedImport::new(path.clone(), item, item, None),
|
import: LocatedImport::new(path.clone(), item, item, None),
|
||||||
scope: import_scope.clone(),
|
scope: import_scope.clone(),
|
||||||
|
@ -505,6 +505,7 @@ fn trait_applicable_items(
|
|||||||
current_crate,
|
current_crate,
|
||||||
&trait_candidates,
|
&trait_candidates,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
|_, assoc| {
|
|_, assoc| {
|
||||||
if required_assoc_items.contains(&assoc) {
|
if required_assoc_items.contains(&assoc) {
|
||||||
if let AssocItem::Function(f) = assoc {
|
if let AssocItem::Function(f) = assoc {
|
||||||
@ -531,6 +532,7 @@ fn trait_applicable_items(
|
|||||||
current_crate,
|
current_crate,
|
||||||
&trait_candidates,
|
&trait_candidates,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
|_, function| {
|
|_, function| {
|
||||||
let assoc = function.as_assoc_item(db)?;
|
let assoc = function.as_assoc_item(db)?;
|
||||||
if required_assoc_items.contains(&assoc) {
|
if required_assoc_items.contains(&assoc) {
|
||||||
|
@ -219,10 +219,12 @@ fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
|
|||||||
let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?;
|
let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?;
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
|
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
|
||||||
let name = path.segment()?.name_ref()?;
|
let name = path.segment()?.name_ref()?;
|
||||||
|
let module = self.scope.module()?;
|
||||||
adt.ty(self.scope.db).iterate_path_candidates(
|
adt.ty(self.scope.db).iterate_path_candidates(
|
||||||
self.scope.db,
|
self.scope.db,
|
||||||
self.scope.module()?.krate(),
|
module.krate(),
|
||||||
&self.scope.visible_traits(),
|
&self.scope.visible_traits(),
|
||||||
|
Some(module),
|
||||||
None,
|
None,
|
||||||
|_ty, assoc_item| {
|
|_ty, assoc_item| {
|
||||||
let item_name = assoc_item.name(self.scope.db)?;
|
let item_name = assoc_item.name(self.scope.db)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user