diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs new file mode 100644 index 000000000..925081ebf --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -0,0 +1,672 @@ +//! 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 + 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 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 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 + 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 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 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 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 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 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 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 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 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 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 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>) + "]], + ); +} + +#[test] +fn complete_record_expr_path() { + check( + r#" +struct Zulu; +impl Zulu { + fn test() -> Self { } +} +fn boi(val: Zulu) { } +fn main() { + boi(Zulu:: $0 {}); +} +"#, + expect![[r#" + fn test() fn() -> Zulu + "#]], + ); +} |