7616: Show `Self` pattern and Self-prefixed enum-variant completions r=Veykril a=Veykril

![jDfQXNE0qZ](https://user-images.githubusercontent.com/3757771/107413514-1ff99b00-6b11-11eb-88b3-126cd106b514.gif)
![JpogVIgloq](https://user-images.githubusercontent.com/3757771/107413519-212ac800-6b11-11eb-8282-51115468dccc.gif)

Variant pattern completions are to be done still.

Closes #6549, at least that should address all that's left from that issue from what I can see.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-02-09 19:38:39 +00:00 committed by GitHub
commit 5d4ae1c8e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 6 deletions

View file

@ -31,6 +31,14 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
_ => false,
},
hir::ScopeDef::MacroDef(_) => true,
hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() {
Some(hir::Adt::Struct(strukt)) => {
acc.add_struct_pat(ctx, strukt, Some(name.clone()));
true
}
Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding,
_ => true,
},
_ => false,
};
if add_resolution {
@ -258,4 +266,24 @@ fn main() {
"#,
);
}
#[test]
fn completes_self_pats() {
check_snippet(
r#"
struct Foo(i32);
impl Foo {
fn foo() {
match () {
$0
}
}
}
"#,
expect![[r#"
bn Self Self($1)$0
bn Foo Foo($1)$0
"#]],
)
}
}

View file

@ -2,7 +2,7 @@
use std::iter;
use hir::{Adt, ModuleDef, ScopeDef, Type};
use hir::{known, Adt, ModuleDef, ScopeDef, Type};
use syntax::AstNode;
use test_utils::mark;
@ -59,6 +59,18 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
enum_data.module(ctx.db)
};
if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
if impl_.target_ty(ctx.db) == *ty {
for &variant in &variants {
let self_path = hir::ModPath::from_segments(
hir::PathKind::Plain,
iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
);
acc.add_qualified_enum_variant(ctx, variant, self_path.clone());
}
}
}
for variant in variants {
if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
// Variants with trivial paths are already added by the existing completion logic,
@ -728,6 +740,28 @@ fn f() -> m::E { V$0 }
)
}
#[test]
fn completes_enum_variant_impl() {
check(
r#"
enum Foo { Bar, Baz, Quux }
impl Foo {
fn foo() { match Foo::Bar { Q$0 } }
}
"#,
expect![[r#"
ev Self::Bar ()
ev Self::Baz ()
ev Self::Quux ()
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
sp Self
en Foo
"#]],
)
}
#[test]
fn dont_complete_attr() {
check(

View file

@ -276,6 +276,14 @@ impl<'a> CompletionContext<'a> {
});
}
fn fill_impl_def(&mut self) {
self.impl_def = self
.sema
.ancestors_with_macros(self.token.parent())
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
.find_map(ast::Impl::cast);
}
fn fill(
&mut self,
original_file: &SyntaxNode,
@ -345,6 +353,8 @@ impl<'a> CompletionContext<'a> {
self.is_irrefutable_pat_binding = true;
}
}
self.fill_impl_def();
}
if is_node::<ast::Param>(name.syntax()) {
self.is_param = true;
@ -372,11 +382,7 @@ impl<'a> CompletionContext<'a> {
self.sema.find_node_at_offset_with_macros(&original_file, offset);
}
self.impl_def = self
.sema
.ancestors_with_macros(self.token.parent())
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
.find_map(ast::Impl::cast);
self.fill_impl_def();
let top_node = name_ref
.syntax()