9299: minor: Filter out non-type completions in the respective completions modules instead r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-06-16 13:10:44 +00:00 committed by GitHub
commit 1c034c084d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 72 deletions

View file

@ -2688,18 +2688,6 @@ impl ScopeDef {
items 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 { impl From<ItemInNs> for ScopeDef {

View file

@ -109,9 +109,6 @@ impl Completions {
local_name: hir::Name, local_name: hir::Name,
resolution: &hir::ScopeDef, resolution: &hir::ScopeDef,
) { ) {
if ctx.expects_type() && resolution.is_value_def() {
return;
}
self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution)); self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution));
} }

View file

@ -19,6 +19,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
Some(res) => res, Some(res) => res,
None => return, None => return,
}; };
let context_module = ctx.scope.module(); let context_module = ctx.scope.module();
if ctx.expects_item() || ctx.expects_assoc_item() { 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 { let add_resolution = match def {
if !macro_def.is_fn_like() {
// Don't suggest attribute macros and derives. // Don't suggest attribute macros and derives.
continue; 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,
};
if add_resolution {
acc.add_resolution(ctx, name, &def); acc.add_resolution(ctx, name, &def);
} }
} }
}
hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_)) hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_))
| hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
| hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def { 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 { let ty = match def {
hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), 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); let ty = a.ty(ctx.db);
if let Some(hir::Adt::Enum(e)) = ty.as_adt() { if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
cov_mark::hit!(completes_variant_through_alias); cov_mark::hit!(completes_variant_through_alias);
add_enum_variants(ctx, acc, e); add_enum_variants(acc, ctx, e);
} }
ty 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)) { if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
return None; return None;
} }
match item { add_assoc_item(acc, ctx, 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),
}
None::<()> 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)) { if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
continue; continue;
} }
match item { add_assoc_item(acc, ctx, 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),
}
} }
} }
hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => { 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() { 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(); 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 // We might iterate candidates of a trait multiple times here, so deduplicate
// them. // them.
if seen.insert(item) { if seen.insert(item) {
match item { add_assoc_item(acc, ctx, 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),
}
} }
None::<()> None::<()>
}); });
@ -176,10 +175,22 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
} }
} }
fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) { fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
for variant in e.variants(ctx.db) { match item {
acc.add_enum_variant(ctx, variant, None); 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)] #[cfg(test)]
@ -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
"#]],
);
}
} }

View file

@ -36,6 +36,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
return; return;
} }
if !ctx.expects_type() {
if let Some(hir::Adt::Enum(e)) = if let Some(hir::Adt::Enum(e)) =
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
{ {
@ -43,6 +44,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
acc.add_qualified_enum_variant(ctx, variant, path) acc.add_qualified_enum_variant(ctx, variant, path)
}); });
} }
}
if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location { if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) { if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) {
@ -59,12 +61,25 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
} }
ctx.scope.process_all_names(&mut |name, res| { 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); cov_mark::hit!(skip_lifetime_completion);
return; return;
} }
let add_resolution = match res { let add_resolution = match res {
// Don't suggest attribute macros and derives.
ScopeDef::MacroDef(mac) => mac.is_fn_like(), 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, _ => true,
}; };
if add_resolution { if add_resolution {
@ -794,36 +809,27 @@ $0
} }
#[test] #[test]
fn completes_assoc_types_in_dynimpl_trait() { fn completes_types_and_const_in_arg_list() {
check( check(
r#" r#"
enum Bar {
Baz
}
trait Foo { trait Foo {
type Bar; type Bar;
} }
fn foo(_: impl Foo<B$0>) {} const CONST: () = ();
"#,
expect![[r#"
ta Bar = type Bar;
tt Foo
"#]],
);
}
#[test] fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {}
fn completes_assoc_types_in_trait_bound() {
check(
r#"
trait Foo {
type Bar;
}
fn foo<T: Foo<B$0>>(_: T) {}
"#, "#,
expect![[r#" expect![[r#"
ta Bar = type Bar; ta Bar = type Bar;
tp T tp T
cp CONST_PARAM
tt Foo tt Foo
en Bar
ct CONST
"#]], "#]],
); );
} }

View file

@ -276,6 +276,10 @@ impl<'a> CompletionContext<'a> {
matches!(self.completion_location, Some(ImmediateLocation::ItemList)) 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 { pub(crate) fn has_block_expr_parent(&self) -> bool {
matches!(self.completion_location, Some(ImmediateLocation::BlockExpr)) matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
} }

View file

@ -55,9 +55,6 @@ pub(crate) fn render_resolution_with_import(
import_edit: ImportEdit, import_edit: ImportEdit,
) -> Option<CompletionItem> { ) -> Option<CompletionItem> {
let resolution = hir::ScopeDef::from(import_edit.import.original_item); 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 { let local_name = match resolution {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,