From b184bfad7a2dc6a9bf6654a7eec6c68a27c49f70 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 20 Dec 2020 18:19:23 +0100 Subject: Add completions for patterns --- crates/completion/src/completions/pattern.rs | 154 ++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 15 deletions(-) (limited to 'crates/completion/src/completions/pattern.rs') diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 4d56731ec..496f0b040 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs @@ -1,10 +1,12 @@ //! Completes constats and paths in patterns. +use hir::StructKind; + use crate::{CompletionContext, Completions}; -/// Completes constats and paths in patterns. +/// Completes constants and paths in patterns. pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { - if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_let_pat_binding) { + if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_pat_binding) { return; } if ctx.record_pat_syntax.is_some() { @@ -15,20 +17,25 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { // suggest variants + auto-imports ctx.scope.process_all_names(&mut |name, res| { let add_resolution = match &res { - hir::ScopeDef::ModuleDef(def) => { - if ctx.is_irrefutable_let_pat_binding { - matches!(def, hir::ModuleDef::Adt(hir::Adt::Struct(_))) - } else { - matches!( - def, - hir::ModuleDef::Adt(hir::Adt::Enum(..)) - | hir::ModuleDef::Adt(hir::Adt::Struct(..)) - | hir::ModuleDef::Variant(..) - | hir::ModuleDef::Const(..) - | hir::ModuleDef::Module(..) - ) + hir::ScopeDef::ModuleDef(def) => match def { + hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => { + acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone())); + true + } + hir::ModuleDef::Variant(variant) + if !ctx.is_irrefutable_pat_binding + // render_resolution already does some pattern completion tricks for tuple variants + && variant.kind(ctx.db) == StructKind::Record => + { + acc.add_variant_pat(ctx, variant.clone(), Some(name.clone())); + true } - } + hir::ModuleDef::Adt(hir::Adt::Enum(..)) + | hir::ModuleDef::Variant(..) + | hir::ModuleDef::Const(..) + | hir::ModuleDef::Module(..) => !ctx.is_irrefutable_pat_binding, + _ => false, + }, hir::ScopeDef::MacroDef(_) => true, _ => false, }; @@ -49,6 +56,11 @@ mod tests { expect.assert_eq(&actual) } + fn check_snippet(ra_fixture: &str, expect: Expect) { + let actual = completion_list(ra_fixture, CompletionKind::Snippet); + expect.assert_eq(&actual) + } + #[test] fn completes_enum_variants_and_modules() { check( @@ -114,4 +126,116 @@ fn foo() { "#]], ); } + + #[test] + fn completes_in_param() { + check( + r#" +enum E { X } + +static FOO: E = E::X; +struct Bar { f: u32 } + +fn foo(<|>) { +} +"#, + expect![[r#" + st Bar + "#]], + ); + } + + #[test] + fn completes_pat_in_let() { + check_snippet( + r#" +struct Bar { f: u32 } + +fn foo() { + let <|> +} +"#, + expect![[r#" + bn Bar Bar { f }$0 + "#]], + ); + } + + #[test] + fn completes_param_pattern() { + check_snippet( + r#" +struct Foo { bar: String, baz: String } +struct Bar(String, String); +struct Baz; +fn outer(<|>) {} +"#, + expect![[r#" + bn Foo Foo { bar, baz }: Foo$0 + bn Bar Bar($1, $2): Bar$0 + "#]], + ) + } + + #[test] + fn completes_let_pattern() { + check_snippet( + r#" +struct Foo { bar: String, baz: String } +struct Bar(String, String); +struct Baz; +fn outer() { + let <|> +} +"#, + expect![[r#" + bn Foo Foo { bar, baz }$0 + bn Bar Bar($1, $2)$0 + "#]], + ) + } + + #[test] + fn completes_refutable_pattern() { + check_snippet( + r#" +struct Foo { bar: i32, baz: i32 } +struct Bar(String, String); +struct Baz; +fn outer() { + match () { + <|> + } +} +"#, + expect![[r#" + bn Foo Foo { bar, baz }$0 + bn Bar Bar($1, $2)$0 + "#]], + ) + } + + #[test] + fn omits_private_fields_pat() { + check_snippet( + r#" +mod foo { + pub struct Foo { pub bar: i32, baz: i32 } + pub struct Bar(pub String, String); + pub struct Invisible(String, String); +} +use foo::*; + +fn outer() { + match () { + <|> + } +} +"#, + expect![[r#" + bn Foo Foo { bar, .. }$0 + bn Bar Bar($1, ..)$0 + "#]], + ) + } } -- cgit v1.2.3