mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-21 01:24:13 +00:00
1322 lines
26 KiB
Rust
1322 lines
26 KiB
Rust
//! Completion tests for expressions.
|
|
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}{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 Unit
|
|
en Enum Enum
|
|
fn baz() fn()
|
|
fn create_foo(…) fn(&FooDesc)
|
|
fn function() fn()
|
|
ma makro!(…) macro_rules! makro
|
|
md _69latrick
|
|
md module
|
|
sc STATIC Unit
|
|
st FooDesc FooDesc
|
|
st Record Record
|
|
st Tuple Tuple
|
|
st Unit Unit
|
|
un Union Union
|
|
ev TupleV(…) TupleV(u32)
|
|
bt u32 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 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
|
|
ex ifletlocal
|
|
ex letlocal
|
|
ex matcharm
|
|
ex param1
|
|
ex param2
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_all_the_things_in_fn_body() {
|
|
check(
|
|
r#"
|
|
use non_existent::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 Unit
|
|
cp CONST_PARAM
|
|
en Enum Enum
|
|
fn function() fn()
|
|
fn local_func() fn()
|
|
me self.foo() fn(self)
|
|
lc self Unit
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
md qualified
|
|
sp Self Unit
|
|
sc STATIC Unit
|
|
st Record Record
|
|
st Tuple Tuple
|
|
st Unit Unit
|
|
tp TypeParam
|
|
un Union Union
|
|
ev TupleV(…) TupleV(u32)
|
|
bt u32 u32
|
|
kw async
|
|
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
|
|
?? Unresolved
|
|
"#]],
|
|
);
|
|
check(
|
|
r#"
|
|
use non_existent::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 Unit
|
|
en Enum Enum
|
|
fn function() fn()
|
|
ma makro!(…) macro_rules! makro
|
|
md module
|
|
md qualified
|
|
sc STATIC Unit
|
|
st Record Record
|
|
st Tuple Tuple
|
|
st Unit Unit
|
|
tt Trait
|
|
un Union 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 u32
|
|
kw async
|
|
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
|
|
ex false
|
|
ex true
|
|
"#]],
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn complete_after_if_expr() {
|
|
check_empty(
|
|
r#"
|
|
fn foo() {
|
|
if true {}
|
|
$0
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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 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 u32
|
|
kw async
|
|
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
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r"fn my() { loop { foo.$0 } }",
|
|
expect![[r#"
|
|
sn box Box::new(expr)
|
|
sn break break expr
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn if if expr {}
|
|
sn let let
|
|
sn letm let mut
|
|
sn match match expr {}
|
|
sn not !expr
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
sn while while expr {}
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_in_let_initializer() {
|
|
check_empty(
|
|
r#"fn main() { let _ = $0 }"#,
|
|
expect![[r#"
|
|
fn main() fn()
|
|
bt u32 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 Foo
|
|
bt u32 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 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 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 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#"
|
|
fn quux(…) fn(i32)
|
|
lc x i32
|
|
lc y i32
|
|
ma m!(…) macro_rules! m
|
|
bt u32 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 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
|
|
ex Zulu
|
|
ex Zulu::test()
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn variant_with_struct() {
|
|
check_empty(
|
|
r#"
|
|
pub struct YoloVariant {
|
|
pub f: usize
|
|
}
|
|
|
|
pub enum HH {
|
|
Yolo(YoloVariant),
|
|
}
|
|
|
|
fn brr() {
|
|
let t = HH::Yolo(Y$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
en HH HH
|
|
fn brr() fn()
|
|
st YoloVariant YoloVariant
|
|
st YoloVariant {…} YoloVariant { f: usize }
|
|
bt u32 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 return_unit_block() {
|
|
cov_mark::check!(return_unit_block);
|
|
check_edit("return", r#"fn f() { if true { $0 } }"#, r#"fn f() { if true { return; } }"#);
|
|
}
|
|
|
|
#[test]
|
|
fn return_unit_no_block() {
|
|
cov_mark::check!(return_unit_no_block);
|
|
check_edit(
|
|
"return",
|
|
r#"fn f() { match () { () => $0 } }"#,
|
|
r#"fn f() { match () { () => return } }"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn return_value_block() {
|
|
cov_mark::check!(return_value_block);
|
|
check_edit(
|
|
"return",
|
|
r#"fn f() -> i32 { if true { $0 } }"#,
|
|
r#"fn f() -> i32 { if true { return $0; } }"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn return_value_no_block() {
|
|
cov_mark::check!(return_value_no_block);
|
|
check_edit(
|
|
"return",
|
|
r#"fn f() -> i32 { match () { () => $0 } }"#,
|
|
r#"fn f() -> i32 { match () { () => return $0 } }"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn else_completion_after_if() {
|
|
check_empty(
|
|
r#"
|
|
fn foo() { if foo {} $0 }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn foo() { if foo {} el$0 }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn foo() { bar(if foo {} $0) }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw crate::
|
|
kw else
|
|
kw else if
|
|
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#"
|
|
fn foo() { bar(if foo {} el$0) }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw crate::
|
|
kw else
|
|
kw else if
|
|
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#"
|
|
fn foo() { if foo {} $0 let x = 92; }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn foo() { if foo {} el$0 let x = 92; }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
fn foo() { if foo {} el$0 { let x = 92; } }
|
|
"#,
|
|
expect![[r#"
|
|
fn foo() fn()
|
|
bt u32 u32
|
|
kw async
|
|
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 expr_no_unstable_item_on_stable() {
|
|
check_empty(
|
|
r#"
|
|
//- /main.rs crate:main deps:std
|
|
use std::*;
|
|
fn main() {
|
|
$0
|
|
}
|
|
//- /std.rs crate:std
|
|
#[unstable]
|
|
pub struct UnstableThisShouldNotBeListed;
|
|
"#,
|
|
expect![[r#"
|
|
fn main() fn()
|
|
md std
|
|
bt u32 u32
|
|
kw async
|
|
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 expr_unstable_item_on_nightly() {
|
|
check_empty(
|
|
r#"
|
|
//- toolchain:nightly
|
|
//- /main.rs crate:main deps:std
|
|
use std::*;
|
|
fn main() {
|
|
$0
|
|
}
|
|
//- /std.rs crate:std
|
|
#[unstable]
|
|
pub struct UnstableButWeAreOnNightlyAnyway;
|
|
"#,
|
|
expect![[r#"
|
|
fn main() fn()
|
|
md std
|
|
st UnstableButWeAreOnNightlyAnyway UnstableButWeAreOnNightlyAnyway
|
|
bt u32 u32
|
|
kw async
|
|
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 inside_format_args_completions_work() {
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("{}", Foo.$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
me foo() fn(&self)
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn match match expr {}
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("{}", Foo.f$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
me foo() fn(&self)
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn match match expr {}
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn inside_faulty_format_args_completions_work() {
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("", Foo.$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
me foo() fn(&self)
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn match match expr {}
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("", Foo.f$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
me foo() fn(&self)
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn match match expr {}
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("{} {named} {captured} {named} {}", a, named = c, Foo.f$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
me foo() fn(&self)
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn match match expr {}
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
"#]],
|
|
);
|
|
check_empty(
|
|
r#"
|
|
//- minicore: fmt
|
|
struct Foo;
|
|
impl Foo {
|
|
fn foo(&self) {}
|
|
}
|
|
|
|
fn main() {
|
|
format_args!("{", Foo.f$0);
|
|
}
|
|
"#,
|
|
expect![[r#"
|
|
sn box Box::new(expr)
|
|
sn call function(expr)
|
|
sn dbg dbg!(expr)
|
|
sn dbgr dbg!(&expr)
|
|
sn deref *expr
|
|
sn if if expr {}
|
|
sn match match expr {}
|
|
sn not !expr
|
|
sn ref &expr
|
|
sn refm &mut expr
|
|
sn return return expr
|
|
sn unsafe unsafe {}
|
|
sn while while expr {}
|
|
"#]],
|
|
);
|
|
}
|