668 lines
13 KiB
Rust
668 lines
13 KiB
Rust
//! Completion tests for expressions.
|
|
use expect_test::{expect, Expect};
|
|
|
|
use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
|
|
|
|
fn check(ra_fixture: &str, expect: Expect) {
|
|
let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
|
|
expect.assert_eq(&actual)
|
|
}
|
|
|
|
fn check_empty(ra_fixture: &str, expect: Expect) {
|
|
let actual = completion_list(ra_fixture);
|
|
expect.assert_eq(&actual);
|
|
}
|
|
|
|
#[test]
|
|
fn complete_literal_struct_with_a_private_field() {
|
|
// `FooDesc.bar` is private, the completion should not be triggered.
|
|
check(
|
|
r#"
|
|
mod _69latrick {
|
|
pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, bar: bool }
|
|
pub fn create_foo(foo_desc: &FooDesc) -> () { () }
|
|
}
|
|
|
|
fn baz() {
|
|
use _69latrick::*;
|
|
|
|
let foo = create_foo(&$0);
|
|
}
|
|
"#,
|
|
// This should not contain `FooDesc {…}`.
|
|
expect![[r#"
|
|
ct CONST
|
|
en Enum
|
|
fn baz() fn()
|
|
fn create_foo(…) fn(&FooDesc)
|
|
fn function() fn()
|
|
ma makro!(…) macro_rules! makro
|
|
md _69latrick
|
|
md module
|
|
sc STATIC
|
|
st FooDesc
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
tt Trait
|
|
un Union
|
|
ev TupleV(…) TupleV(u32)
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw mut
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_various_bindings() {
|
|
check_empty(
|
|
r#"
|
|
fn func(param0 @ (param1, param2): (i32, i32)) {
|
|
let letlocal = 92;
|
|
if let ifletlocal = 100 {
|
|
match 0 {
|
|
matcharm => 1 + $0,
|
|
otherwise => (),
|
|
}
|
|
}
|
|
let letlocal2 = 44;
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn func(…) fn((i32, i32))
|
|
lc ifletlocal i32
|
|
lc letlocal i32
|
|
lc matcharm i32
|
|
lc param0 (i32, i32)
|
|
lc param1 i32
|
|
lc param2 i32
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_all_the_things_in_fn_body() {
|
|
check(
|
|
r#"
|
|
use non_existant::Unresolved;
|
|
mod qualified { pub enum Enum { Variant } }
|
|
|
|
impl Unit {
|
|
fn foo<'lifetime, TypeParam, const CONST_PARAM: usize>(self) {
|
|
fn local_func() {}
|
|
$0
|
|
}
|
|
}
|
|
"#,
|
|
// `self` is in here twice, once as the module, once as the local
|
|
expect![[r#"
|
|
ct CONST
|
|
cp CONST_PARAM
|
|
en Enum
|
|
fn function() fn()
|
|
fn local_func() fn()
|
|
lc self Unit
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
md qualified
|
|
sp Self
|
|
sc STATIC
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
tt Trait
|
|
tp TypeParam
|
|
un Union
|
|
ev TupleV(…) TupleV(u32)
|
|
bt u32
|
|
kw const
|
|
kw crate::
|
|
kw enum
|
|
kw extern
|
|
kw false
|
|
kw fn
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw impl
|
|
kw let
|
|
kw loop
|
|
kw match
|
|
kw mod
|
|
kw return
|
|
kw self::
|
|
kw static
|
|
kw struct
|
|
kw super::
|
|
kw trait
|
|
kw true
|
|
kw type
|
|
kw union
|
|
kw unsafe
|
|
kw use
|
|
kw while
|
|
kw while let
|
|
me self.foo() fn(self)
|
|
sn macro_rules
|
|
sn pd
|
|
sn ppd
|
|
?? Unresolved
|
|
"#]],
|
|
);
|
|
check(
|
|
r#"
|
|
use non_existant::Unresolved;
|
|
mod qualified { pub enum Enum { Variant } }
|
|
|
|
impl Unit {
|
|
fn foo<'lifetime, TypeParam, const CONST_PARAM: usize>(self) {
|
|
fn local_func() {}
|
|
self::$0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct CONST
|
|
en Enum
|
|
fn function() fn()
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
md qualified
|
|
sc STATIC
|
|
st Record
|
|
st Tuple
|
|
st Unit
|
|
tt Trait
|
|
un Union
|
|
ev TupleV(…) TupleV(u32)
|
|
?? Unresolved
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn complete_in_block() {
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
if true {
|
|
$0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32
|
|
kw const
|
|
kw crate::
|
|
kw enum
|
|
kw extern
|
|
kw false
|
|
kw fn
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw impl
|
|
kw let
|
|
kw loop
|
|
kw match
|
|
kw mod
|
|
kw return
|
|
kw self::
|
|
kw static
|
|
kw struct
|
|
kw super::
|
|
kw trait
|
|
kw true
|
|
kw type
|
|
kw union
|
|
kw unsafe
|
|
kw use
|
|
kw while
|
|
kw while let
|
|
sn macro_rules
|
|
sn pd
|
|
sn ppd
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn complete_after_if_expr() {
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
if true {}
|
|
$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32
|
|
kw const
|
|
kw crate::
|
|
kw else
|
|
kw else if
|
|
kw enum
|
|
kw extern
|
|
kw false
|
|
kw fn
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw impl
|
|
kw let
|
|
kw loop
|
|
kw match
|
|
kw mod
|
|
kw return
|
|
kw self::
|
|
kw static
|
|
kw struct
|
|
kw super::
|
|
kw trait
|
|
kw true
|
|
kw type
|
|
kw union
|
|
kw unsafe
|
|
kw use
|
|
kw while
|
|
kw while let
|
|
sn macro_rules
|
|
sn pd
|
|
sn ppd
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn complete_in_match_arm() {
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
match () {
|
|
() => $0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_loop_ctx() {
|
|
check_empty(
|
|
r"fn my() { loop { $0 } }",
|
|
expect![[r#"
|
|
fn my() fn()
|
|
bt u32
|
|
kw break
|
|
kw const
|
|
kw continue
|
|
kw crate::
|
|
kw enum
|
|
kw extern
|
|
kw false
|
|
kw fn
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw impl
|
|
kw let
|
|
kw loop
|
|
kw match
|
|
kw mod
|
|
kw return
|
|
kw self::
|
|
kw static
|
|
kw struct
|
|
kw super::
|
|
kw trait
|
|
kw true
|
|
kw type
|
|
kw union
|
|
kw unsafe
|
|
kw use
|
|
kw while
|
|
kw while let
|
|
sn macro_rules
|
|
sn pd
|
|
sn ppd
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_let_initializer() {
|
|
check_empty(
|
|
r#"fn main() { let _ = $0 }"#,
|
|
expect![[r#"
|
|
fn main() fn()
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn struct_initializer_field_expr() {
|
|
check_empty(
|
|
r#"
|
|
struct Foo {
|
|
pub f: i32,
|
|
}
|
|
fn foo() {
|
|
Foo {
|
|
f: $0
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
st Foo
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn shadowing_shows_single_completion() {
|
|
cov_mark::check!(shadowing_shows_single_completion);
|
|
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
let bar = 92;
|
|
{
|
|
let bar = 62;
|
|
drop($0)
|
|
}
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
lc bar i32
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_macro_expr_frag() {
|
|
check_empty(
|
|
r#"
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
fn quux(x: i32) {
|
|
m!($0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn quux(…) fn(i32)
|
|
lc x i32
|
|
ma m!(…) macro_rules! m
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r"
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
fn quux(x: i32) {
|
|
m!(x$0);
|
|
}
|
|
",
|
|
expect![[r#"
|
|
fn quux(…) fn(i32)
|
|
lc x i32
|
|
ma m!(…) macro_rules! m
|
|
bt u32
|
|
kw crate::
|
|
kw false
|
|
kw for
|
|
kw if
|
|
kw if let
|
|
kw loop
|
|
kw match
|
|
kw return
|
|
kw self::
|
|
kw super::
|
|
kw true
|
|
kw unsafe
|
|
kw while
|
|
kw while let
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
fn quux(x: i32) {
|
|
let y = 92;
|
|
m!(x$0
|
|
}
|
|
"#,
|
|
expect![[r#""#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_qualified() {
|
|
check(
|
|
r#"
|
|
impl Enum {
|
|
type AssocType = ();
|
|
const ASSOC_CONST: () = ();
|
|
fn assoc_fn() {}
|
|
}
|
|
fn func() {
|
|
Enum::$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
ct ASSOC_CONST const ASSOC_CONST: ()
|
|
fn assoc_fn() fn()
|
|
ta AssocType type AssocType = ()
|
|
ev RecordV {…} RecordV { field: u32 }
|
|
ev TupleV(…) TupleV(u32)
|
|
ev UnitV UnitV
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ty_qualified_no_drop() {
|
|
check_empty(
|
|
r#"
|
|
//- minicore: drop
|
|
struct Foo;
|
|
impl Drop for Foo {
|
|
fn drop(&mut self) {}
|
|
}
|
|
fn func() {
|
|
Foo::$0
|
|
}
|
|
"#,
|
|
expect![[r#""#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn with_parens() {
|
|
check_empty(
|
|
r#"
|
|
enum Enum {
|
|
Variant()
|
|
}
|
|
impl Enum {
|
|
fn variant() -> Self { Enum::Variant() }
|
|
}
|
|
fn func() {
|
|
Enum::$0()
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn variant fn() -> Enum
|
|
ev Variant Variant
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn detail_impl_trait_in_return_position() {
|
|
check_empty(
|
|
r"
|
|
//- minicore: sized
|
|
trait Trait<T> {}
|
|
fn foo<U>() -> impl Trait<U> {}
|
|
fn main() {
|
|
self::$0
|
|
}
|
|
",
|
|
expect![[r#"
|
|
fn foo() fn() -> impl Trait<U>
|
|
fn main() fn()
|
|
tt Trait
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn detail_async_fn() {
|
|
check_empty(
|
|
r#"
|
|
//- minicore: future, sized
|
|
trait Trait<T> {}
|
|
async fn foo() -> u8 {}
|
|
async fn bar<U>() -> impl Trait<U> {}
|
|
fn main() {
|
|
self::$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn bar() async fn() -> impl Trait<U>
|
|
fn foo() async fn() -> u8
|
|
fn main() fn()
|
|
tt Trait
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn detail_impl_trait_in_argument_position() {
|
|
check_empty(
|
|
r"
|
|
//- minicore: sized
|
|
trait Trait<T> {}
|
|
struct Foo;
|
|
impl Foo {
|
|
fn bar<U>(_: impl Trait<U>) {}
|
|
}
|
|
fn main() {
|
|
Foo::$0
|
|
}
|
|
",
|
|
expect![[r"
|
|
fn bar(…) fn(impl Trait<U>)
|
|
"]],
|
|
);
|
|
}
|