822 lines
13 KiB
Rust
822 lines
13 KiB
Rust
//! Completion tests for pattern position.
|
|
use expect_test::{expect, Expect};
|
|
|
|
use crate::tests::{check_edit, check_empty, completion_list, BASE_ITEMS_FIXTURE};
|
|
|
|
fn check(ra_fixture: &str, expect: Expect) {
|
|
let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}"));
|
|
expect.assert_eq(&actual)
|
|
}
|
|
|
|
#[test]
|
|
fn wildcard() {
|
|
check(
|
|
r#"
|
|
fn quux() {
|
|
let _$0
|
|
}
|
|
"#,
|
|
expect![""],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ident_rebind_pat() {
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let en$0 @ x
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ident_ref_pat() {
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let ref en$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let ref en$0 @ x
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ident_ref_mut_pat() {
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let ref mut en$0
|
|
}
|
|
"#,
|
|
expect![[r#""#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let ref mut en$0 @ x
|
|
}
|
|
"#,
|
|
expect![[r#""#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ref_pat() {
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let &en$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn quux() {
|
|
let &mut en$0
|
|
}
|
|
"#,
|
|
expect![[r#""#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
for &$0 in () {}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn refutable() {
|
|
check(
|
|
r#"
|
|
fn foo() {
|
|
if let a$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct CONST
|
|
en Enum
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
ev TupleV
|
|
bn Record {…} Record { field$1 }$0
|
|
bn Tuple(…) Tuple($1)$0
|
|
bn TupleV(…) TupleV($1)$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn irrefutable() {
|
|
check(
|
|
r#"
|
|
enum SingleVariantEnum {
|
|
Variant
|
|
}
|
|
use SingleVariantEnum::Variant;
|
|
fn foo() {
|
|
let a$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
en SingleVariantEnum
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
ev Variant
|
|
bn Record {…} Record { field$1 }$0
|
|
bn Tuple(…) Tuple($1)$0
|
|
bn Variant Variant$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_param() {
|
|
check(
|
|
r#"
|
|
fn foo(a$0) {
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
bn Record {…} Record { field$1 }: Record$0
|
|
bn Tuple(…) Tuple($1): Tuple$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
check(
|
|
r#"
|
|
fn foo(a$0: Tuple) {
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
bn Record {…} Record { field$1 }$0
|
|
bn Tuple(…) Tuple($1)$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn only_fn_like_macros() {
|
|
check_empty(
|
|
r#"
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
|
|
#[rustc_builtin_macro]
|
|
macro Clone {}
|
|
|
|
fn foo() {
|
|
let x$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ma m!(…) macro_rules! m
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_simple_macro_call() {
|
|
check_empty(
|
|
r#"
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
enum E { X }
|
|
|
|
fn foo() {
|
|
m!(match E::X { a$0 })
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
en E
|
|
ma m!(…) macro_rules! m
|
|
bn E::X E::X$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn omits_private_fields_pat() {
|
|
check_empty(
|
|
r#"
|
|
mod foo {
|
|
pub struct Record { pub field: i32, _field: i32 }
|
|
pub struct Tuple(pub u32, u32);
|
|
pub struct Invisible(u32, u32);
|
|
}
|
|
use foo::*;
|
|
|
|
fn outer() {
|
|
if let a$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
md foo
|
|
st Invisible
|
|
st Record
|
|
st Tuple
|
|
bn Record {…} Record { field$1, .. }$0
|
|
bn Tuple(…) Tuple($1, ..)$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_self_pats() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo(i32);
|
|
impl Foo {
|
|
fn foo() {
|
|
match Foo(0) {
|
|
a$0
|
|
}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sp Self
|
|
st Foo
|
|
bn Foo(…) Foo($1)$0
|
|
bn Self(…) Self($1)$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn enum_qualified() {
|
|
check(
|
|
r#"
|
|
impl Enum {
|
|
type AssocType = ();
|
|
const ASSOC_CONST: () = ();
|
|
fn assoc_fn() {}
|
|
}
|
|
fn func() {
|
|
if let Enum::$0 = unknown {}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct ASSOC_CONST const ASSOC_CONST: ()
|
|
bn RecordV {…} RecordV { field$1 }$0
|
|
bn TupleV(…) TupleV($1)$0
|
|
bn UnitV UnitV$0
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_record_field_pat() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo { bar: Bar }
|
|
struct Bar(u32);
|
|
fn outer(Foo { bar: $0 }: Foo) {}
|
|
"#,
|
|
expect![[r#"
|
|
st Bar
|
|
st Foo
|
|
bn Bar(…) Bar($1)$0
|
|
bn Foo {…} Foo { bar$1 }$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn skips_in_record_field_pat_name() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo { bar: Bar }
|
|
struct Bar(u32);
|
|
fn outer(Foo { bar$0 }: Foo) {}
|
|
"#,
|
|
expect![[r#"
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_record_field_pat_with_generic_type_alias() {
|
|
check_empty(
|
|
r#"
|
|
type Wrap<T> = T;
|
|
|
|
enum X {
|
|
A { cool: u32, stuff: u32 },
|
|
B,
|
|
}
|
|
|
|
fn main() {
|
|
let wrapped = Wrap::<X>::A {
|
|
cool: 100,
|
|
stuff: 100,
|
|
};
|
|
|
|
if let Wrap::<X>::A { $0 } = &wrapped {};
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fd cool u32
|
|
fd stuff u32
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_fn_param() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo { bar: Bar }
|
|
struct Bar(u32);
|
|
fn foo($0) {}
|
|
"#,
|
|
expect![[r#"
|
|
st Bar
|
|
st Foo
|
|
bn Bar(…) Bar($1): Bar$0
|
|
bn Foo {…} Foo { bar$1 }: Foo$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_closure_param() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo { bar: Bar }
|
|
struct Bar(u32);
|
|
fn foo() {
|
|
|$0| {};
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
st Bar
|
|
st Foo
|
|
bn Bar(…) Bar($1)$0
|
|
bn Foo {…} Foo { bar$1 }$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_no_delims_if_existing() {
|
|
check_empty(
|
|
r#"
|
|
struct Bar(u32);
|
|
fn foo() {
|
|
match Bar(0) {
|
|
B$0(b) => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
st Bar Bar
|
|
kw crate::
|
|
kw self::
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
struct Foo { bar: u32 }
|
|
fn foo() {
|
|
match (Foo { bar: 0 }) {
|
|
F$0 { bar } => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
st Foo Foo
|
|
kw crate::
|
|
kw self::
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
enum Enum {
|
|
TupleVariant(u32)
|
|
}
|
|
fn foo() {
|
|
match Enum::TupleVariant(0) {
|
|
Enum::T$0(b) => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
bn TupleVariant TupleVariant
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
enum Enum {
|
|
RecordVariant { field: u32 }
|
|
}
|
|
fn foo() {
|
|
match (Enum::RecordVariant { field: 0 }) {
|
|
Enum::RecordV$0 { field } => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
bn RecordVariant RecordVariant
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_enum_variant_pat() {
|
|
cov_mark::check!(enum_variant_pattern_path);
|
|
check_edit(
|
|
"RecordVariant{}",
|
|
r#"
|
|
enum Enum {
|
|
RecordVariant { field: u32 }
|
|
}
|
|
fn foo() {
|
|
match (Enum::RecordVariant { field: 0 }) {
|
|
Enum::RecordV$0
|
|
}
|
|
}
|
|
"#,
|
|
r#"
|
|
enum Enum {
|
|
RecordVariant { field: u32 }
|
|
}
|
|
fn foo() {
|
|
match (Enum::RecordVariant { field: 0 }) {
|
|
Enum::RecordVariant { field$1 }$0
|
|
}
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_enum_variant_pat_escape() {
|
|
cov_mark::check!(enum_variant_pattern_path);
|
|
check_empty(
|
|
r#"
|
|
enum Enum {
|
|
A,
|
|
B { r#type: i32 },
|
|
r#type,
|
|
r#struct { r#type: i32 },
|
|
}
|
|
fn foo() {
|
|
match (Enum::A) {
|
|
$0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
en Enum
|
|
bn Enum::A Enum::A$0
|
|
bn Enum::B {…} Enum::B { r#type$1 }$0
|
|
bn Enum::struct {…} Enum::r#struct { r#type$1 }$0
|
|
bn Enum::type Enum::r#type$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
|
|
check_empty(
|
|
r#"
|
|
enum Enum {
|
|
A,
|
|
B { r#type: i32 },
|
|
r#type,
|
|
r#struct { r#type: i32 },
|
|
}
|
|
fn foo() {
|
|
match (Enum::A) {
|
|
Enum::$0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
bn A A$0
|
|
bn B {…} B { r#type$1 }$0
|
|
bn struct {…} r#struct { r#type$1 }$0
|
|
bn type r#type$0
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_associated_const() {
|
|
check_empty(
|
|
r#"
|
|
#[derive(PartialEq, Eq)]
|
|
struct Ty(u8);
|
|
|
|
impl Ty {
|
|
const ABC: Self = Self(0);
|
|
}
|
|
|
|
fn f(t: Ty) {
|
|
match t {
|
|
Ty::$0 => {}
|
|
_ => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct ABC const ABC: Self
|
|
"#]],
|
|
);
|
|
|
|
check_empty(
|
|
r#"
|
|
enum MyEnum {}
|
|
|
|
impl MyEnum {
|
|
pub const A: i32 = 123;
|
|
pub const B: i32 = 456;
|
|
}
|
|
|
|
fn f(e: MyEnum) {
|
|
match e {
|
|
MyEnum::$0 => {}
|
|
_ => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct A pub const A: i32
|
|
ct B pub const B: i32
|
|
"#]],
|
|
);
|
|
|
|
check_empty(
|
|
r#"
|
|
union U {
|
|
i: i32,
|
|
f: f32,
|
|
}
|
|
|
|
impl U {
|
|
pub const C: i32 = 123;
|
|
pub const D: i32 = 456;
|
|
}
|
|
|
|
fn f(u: U) {
|
|
match u {
|
|
U::$0 => {}
|
|
_ => {}
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct C pub const C: i32
|
|
ct D pub const D: i32
|
|
"#]],
|
|
);
|
|
|
|
check_empty(
|
|
r#"
|
|
#![rustc_coherence_is_core]
|
|
#[lang = "u32"]
|
|
impl u32 {
|
|
pub const MIN: Self = 0;
|
|
}
|
|
|
|
fn f(v: u32) {
|
|
match v {
|
|
u32::$0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct MIN pub const MIN: Self
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_method_param() {
|
|
check_empty(
|
|
r#"
|
|
struct Ty(u8);
|
|
|
|
impl Ty {
|
|
fn foo($0)
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sp Self
|
|
st Ty
|
|
bn &mut self
|
|
bn &self
|
|
bn Self(…) Self($1): Self$0
|
|
bn Ty(…) Ty($1): Ty$0
|
|
bn mut self
|
|
bn self
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
struct Ty(u8);
|
|
|
|
impl Ty {
|
|
fn foo(s$0)
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sp Self
|
|
st Ty
|
|
bn &mut self
|
|
bn &self
|
|
bn Self(…) Self($1): Self$0
|
|
bn Ty(…) Ty($1): Ty$0
|
|
bn mut self
|
|
bn self
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
struct Ty(u8);
|
|
|
|
impl Ty {
|
|
fn foo(s$0, foo: u8)
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sp Self
|
|
st Ty
|
|
bn &mut self
|
|
bn &self
|
|
bn Self(…) Self($1): Self$0
|
|
bn Ty(…) Ty($1): Ty$0
|
|
bn mut self
|
|
bn self
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
struct Ty(u8);
|
|
|
|
impl Ty {
|
|
fn foo(foo: u8, b$0)
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sp Self
|
|
st Ty
|
|
bn Self(…) Self($1): Self$0
|
|
bn Ty(…) Ty($1): Ty$0
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn through_alias() {
|
|
check_empty(
|
|
r#"
|
|
enum Enum<T> {
|
|
Unit,
|
|
Tuple(T),
|
|
}
|
|
|
|
type EnumAlias<T> = Enum<T>;
|
|
|
|
fn f(x: EnumAlias<u8>) {
|
|
match x {
|
|
EnumAlias::$0 => (),
|
|
_ => (),
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
expect![[r#"
|
|
bn Tuple(…) Tuple($1)$0
|
|
bn Unit Unit$0
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn pat_no_unstable_item_on_stable() {
|
|
check_empty(
|
|
r#"
|
|
//- /main.rs crate:main deps:std
|
|
use std::*;
|
|
fn foo() {
|
|
let a$0
|
|
}
|
|
//- /std.rs crate:std
|
|
#[unstable]
|
|
pub struct S;
|
|
#[unstable]
|
|
pub enum Enum {
|
|
Variant
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
md std
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn pat_unstable_item_on_nightly() {
|
|
check_empty(
|
|
r#"
|
|
//- toolchain:nightly
|
|
//- /main.rs crate:main deps:std
|
|
use std::*;
|
|
fn foo() {
|
|
let a$0
|
|
}
|
|
//- /std.rs crate:std
|
|
#[unstable]
|
|
pub struct S;
|
|
#[unstable]
|
|
pub enum Enum {
|
|
Variant
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
en Enum
|
|
md std
|
|
st S
|
|
kw mut
|
|
kw ref
|
|
"#]],
|
|
);
|
|
}
|