Filter out non-type completions in the respective completions modules instead
This commit is contained in:
parent
79703efc7f
commit
354ad29493
@ -2688,18 +2688,6 @@ impl ScopeDef {
|
||||
|
||||
items
|
||||
}
|
||||
|
||||
pub fn is_value_def(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ScopeDef::ModuleDef(ModuleDef::Function(_))
|
||||
| ScopeDef::ModuleDef(ModuleDef::Variant(_))
|
||||
| ScopeDef::ModuleDef(ModuleDef::Const(_))
|
||||
| ScopeDef::ModuleDef(ModuleDef::Static(_))
|
||||
| ScopeDef::GenericParam(GenericParam::ConstParam(_))
|
||||
| ScopeDef::Local(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ItemInNs> for ScopeDef {
|
||||
|
@ -109,9 +109,6 @@ impl Completions {
|
||||
local_name: hir::Name,
|
||||
resolution: &hir::ScopeDef,
|
||||
) {
|
||||
if ctx.expects_type() && resolution.is_value_def() {
|
||||
return;
|
||||
}
|
||||
self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution));
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
Some(res) => res,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let context_module = ctx.scope.module();
|
||||
|
||||
if ctx.expects_item() || ctx.expects_assoc_item() {
|
||||
@ -60,21 +61,31 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
}
|
||||
}
|
||||
|
||||
if let hir::ScopeDef::MacroDef(macro_def) = def {
|
||||
if !macro_def.is_fn_like() {
|
||||
// Don't suggest attribute macros and derives.
|
||||
continue;
|
||||
let add_resolution = match def {
|
||||
// Don't suggest attribute macros and derives.
|
||||
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
||||
// no values in type places
|
||||
hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
|
||||
| hir::ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
|
||||
| hir::ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
|
||||
| hir::ScopeDef::Local(_) => !ctx.expects_type(),
|
||||
// unless its a constant in a generic arg list position
|
||||
hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
|
||||
!ctx.expects_type() || ctx.expects_generic_arg()
|
||||
}
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
|
||||
acc.add_resolution(ctx, name, &def);
|
||||
if add_resolution {
|
||||
acc.add_resolution(ctx, name, &def);
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_))
|
||||
| hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
|
||||
| hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
|
||||
if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
|
||||
add_enum_variants(ctx, acc, e);
|
||||
add_enum_variants(acc, ctx, e);
|
||||
}
|
||||
let ty = match def {
|
||||
hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
|
||||
@ -82,7 +93,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
let ty = a.ty(ctx.db);
|
||||
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
|
||||
cov_mark::hit!(completes_variant_through_alias);
|
||||
add_enum_variants(ctx, acc, e);
|
||||
add_enum_variants(acc, ctx, e);
|
||||
}
|
||||
ty
|
||||
}
|
||||
@ -107,11 +118,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
|
||||
return None;
|
||||
}
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
|
||||
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
}
|
||||
add_assoc_item(acc, ctx, item);
|
||||
None::<()>
|
||||
});
|
||||
|
||||
@ -133,11 +140,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
|
||||
continue;
|
||||
}
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
|
||||
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
}
|
||||
add_assoc_item(acc, ctx, item);
|
||||
}
|
||||
}
|
||||
hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
|
||||
@ -149,7 +152,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
};
|
||||
|
||||
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
|
||||
add_enum_variants(ctx, acc, e);
|
||||
add_enum_variants(acc, ctx, e);
|
||||
}
|
||||
|
||||
let traits_in_scope = ctx.scope.traits_in_scope();
|
||||
@ -162,11 +165,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
// We might iterate candidates of a trait multiple times here, so deduplicate
|
||||
// them.
|
||||
if seen.insert(item) {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
|
||||
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
}
|
||||
add_assoc_item(acc, ctx, item);
|
||||
}
|
||||
None::<()>
|
||||
});
|
||||
@ -176,12 +175,24 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
}
|
||||
}
|
||||
|
||||
fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) {
|
||||
for variant in e.variants(ctx.db) {
|
||||
acc.add_enum_variant(ctx, variant, None);
|
||||
fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
|
||||
match item {
|
||||
hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
|
||||
hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
|
||||
acc.add_const(ctx, ct)
|
||||
}
|
||||
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
|
||||
if ctx.expects_type() {
|
||||
return;
|
||||
}
|
||||
e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use expect_test::{expect, Expect};
|
||||
@ -927,4 +938,24 @@ fn main() {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_types_and_const_in_arg_list() {
|
||||
check(
|
||||
r#"
|
||||
mod foo {
|
||||
pub const CONST: () = ();
|
||||
pub type Type = ();
|
||||
}
|
||||
|
||||
struct Foo<T>(t);
|
||||
|
||||
fn foo(_: Foo<foo::$0>) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ta Type
|
||||
ct CONST
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -36,12 +36,14 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(hir::Adt::Enum(e)) =
|
||||
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
|
||||
{
|
||||
super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| {
|
||||
acc.add_qualified_enum_variant(ctx, variant, path)
|
||||
});
|
||||
if !ctx.expects_type() {
|
||||
if let Some(hir::Adt::Enum(e)) =
|
||||
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
|
||||
{
|
||||
super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| {
|
||||
acc.add_qualified_enum_variant(ctx, variant, path)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
|
||||
@ -59,12 +61,25 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||
}
|
||||
|
||||
ctx.scope.process_all_names(&mut |name, res| {
|
||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
|
||||
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) =
|
||||
res
|
||||
{
|
||||
cov_mark::hit!(skip_lifetime_completion);
|
||||
return;
|
||||
}
|
||||
let add_resolution = match res {
|
||||
// Don't suggest attribute macros and derives.
|
||||
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
|
||||
// no values in type places
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
|
||||
| ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
|
||||
| ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
|
||||
| ScopeDef::Local(_) => !ctx.expects_type(),
|
||||
// unless its a constant in a generic arg list position
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Const(_))
|
||||
| ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => {
|
||||
!ctx.expects_type() || ctx.expects_generic_arg()
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
if add_resolution {
|
||||
@ -794,36 +809,27 @@ $0
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_assoc_types_in_dynimpl_trait() {
|
||||
fn completes_types_and_const_in_arg_list() {
|
||||
check(
|
||||
r#"
|
||||
enum Bar {
|
||||
Baz
|
||||
}
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
fn foo(_: impl Foo<B$0>) {}
|
||||
const CONST: () = ();
|
||||
|
||||
fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ta Bar = type Bar;
|
||||
tt Foo
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_assoc_types_in_trait_bound() {
|
||||
check(
|
||||
r#"
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
fn foo<T: Foo<B$0>>(_: T) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ta Bar = type Bar;
|
||||
ta Bar = type Bar;
|
||||
tp T
|
||||
cp CONST_PARAM
|
||||
tt Foo
|
||||
en Bar
|
||||
ct CONST
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -276,6 +276,10 @@ impl<'a> CompletionContext<'a> {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::ItemList))
|
||||
}
|
||||
|
||||
pub(crate) fn expects_generic_arg(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::GenericArgList(_)))
|
||||
}
|
||||
|
||||
pub(crate) fn has_block_expr_parent(&self) -> bool {
|
||||
matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
|
||||
}
|
||||
|
@ -55,9 +55,6 @@ pub(crate) fn render_resolution_with_import(
|
||||
import_edit: ImportEdit,
|
||||
) -> Option<CompletionItem> {
|
||||
let resolution = hir::ScopeDef::from(import_edit.import.original_item);
|
||||
if ctx.completion.expects_type() && resolution.is_value_def() {
|
||||
return None;
|
||||
}
|
||||
let local_name = match resolution {
|
||||
hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
|
||||
hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
|
||||
|
Loading…
x
Reference in New Issue
Block a user