Modernize completion presentation tests

This commit is contained in:
Aleksey Kladov 2020-07-04 09:35:44 +02:00
parent 65768feaff
commit aaba2300fb

View File

@ -330,14 +330,14 @@ pub(crate) fn compute_score(
// FIXME: this should not fall back to string equality.
let ty = &ty.display(ctx.db).to_string();
let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
mark::hit!(test_struct_field_completion_in_record_lit);
mark::hit!(record_field_type_match);
let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
(
struct_field.name(ctx.db).to_string(),
struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
)
} else if let Some(active_parameter) = &ctx.active_parameter {
mark::hit!(test_struct_field_completion_in_func_call);
mark::hit!(active_param_type_match);
(active_parameter.name.clone(), active_parameter.ty.clone())
} else {
return None;
@ -461,63 +461,56 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
#[cfg(test)]
mod tests {
use insta::assert_debug_snapshot;
use expect::{expect, Expect};
use test_utils::mark;
use crate::completion::{
test_utils::{check_edit, check_edit_with_config, do_completion},
CompletionConfig, CompletionItem, CompletionKind,
CompletionConfig, CompletionKind,
};
fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> {
do_completion(ra_fixture, CompletionKind::Reference)
fn check(ra_fixture: &str, expect: Expect) {
let actual = do_completion(ra_fixture, CompletionKind::Reference);
expect.assert_debug_eq(&actual);
}
#[test]
fn enum_detail_includes_names_for_record() {
assert_debug_snapshot!(
do_reference_completion(
fn enum_detail_includes_record_fields() {
check(
r#"
enum Foo {
Foo {x: i32, y: i32}
}
enum Foo { Foo { x: i32, y: i32 } }
fn main() { Foo::Fo<|> }
"#,
),
@r###"
fn main() { Foo::Fo<|> }
"#,
expect![[r#"
[
CompletionItem {
label: "Foo",
source_range: 56..58,
delete: 56..58,
source_range: 54..56,
delete: 54..56,
insert: "Foo",
kind: EnumVariant,
detail: "{ x: i32, y: i32 }",
},
]
"###
"#]],
);
}
#[test]
fn enum_detail_doesnt_include_names_for_tuple() {
assert_debug_snapshot!(
do_reference_completion(
fn enum_detail_doesnt_include_tuple_fields() {
check(
r#"
enum Foo {
Foo (i32, i32)
}
enum Foo { Foo (i32, i32) }
fn main() { Foo::Fo<|> }
"#,
),
@r###"
fn main() { Foo::Fo<|> }
"#,
expect![[r#"
[
CompletionItem {
label: "Foo(…)",
source_range: 50..52,
delete: 50..52,
source_range: 46..48,
delete: 46..48,
insert: "Foo($0)",
kind: EnumVariant,
lookup: "Foo",
@ -525,57 +518,50 @@ mod tests {
trigger_call_info: true,
},
]
"###
"#]],
);
}
#[test]
fn enum_detail_just_parentheses_for_unit() {
assert_debug_snapshot!(
do_reference_completion(
check(
r#"
enum Foo {
Foo
}
enum Foo { Foo }
fn main() { Foo::Fo<|> }
"#,
),
@r###"
fn main() { Foo::Fo<|> }
"#,
expect![[r#"
[
CompletionItem {
label: "Foo",
source_range: 39..41,
delete: 39..41,
source_range: 35..37,
delete: 35..37,
insert: "Foo",
kind: EnumVariant,
detail: "()",
},
]
"###
"#]],
);
}
#[test]
fn sets_deprecated_flag_in_completion_items() {
assert_debug_snapshot!(
do_reference_completion(
check(
r#"
#[deprecated]
fn something_deprecated() {}
#[deprecated]
fn something_deprecated() {}
#[deprecated(since = "1.0.0")]
fn something_else_deprecated() {}
#[deprecated(since = "1.0.0")]
fn something_else_deprecated() {}
fn main() { som<|> }
"#,
),
@r###"
fn main() { som<|> }
"#,
expect![[r#"
[
CompletionItem {
label: "main()",
source_range: 122..125,
delete: 122..125,
source_range: 121..124,
delete: 121..124,
insert: "main()$0",
kind: Function,
lookup: "main",
@ -583,8 +569,8 @@ mod tests {
},
CompletionItem {
label: "something_deprecated()",
source_range: 122..125,
delete: 122..125,
source_range: 121..124,
delete: 121..124,
insert: "something_deprecated()$0",
kind: Function,
lookup: "something_deprecated",
@ -593,8 +579,8 @@ mod tests {
},
CompletionItem {
label: "something_else_deprecated()",
source_range: 122..125,
delete: 122..125,
source_range: 121..124,
delete: 121..124,
insert: "something_else_deprecated()$0",
kind: Function,
lookup: "something_else_deprecated",
@ -602,33 +588,28 @@ mod tests {
deprecated: true,
},
]
"###
"#]],
);
assert_debug_snapshot!(do_reference_completion(
check(
r#"
struct A {
#[deprecated]
the_field: u32,
}
fn foo() {
A { the<|> }
}
struct A { #[deprecated] the_field: u32 }
fn foo() { A { the<|> } }
"#,
),
@r###"
expect![[r#"
[
CompletionItem {
label: "the_field",
source_range: 69..72,
delete: 69..72,
source_range: 57..60,
delete: 57..60,
insert: "the_field",
kind: Field,
detail: "u32",
deprecated: true,
},
]
"###);
"#]],
);
}
#[test]
@ -921,262 +902,228 @@ fn main() { frobnicate!(); }
}
#[test]
fn test_struct_field_completion_in_func_call() {
mark::check!(test_struct_field_completion_in_func_call);
assert_debug_snapshot!(
do_reference_completion(
r"
struct A { another_field: i64, the_field: u32, my_string: String }
fn test(my_param: u32) -> u32 { my_param }
fn foo(a: A) {
test(a.<|>)
}
",
),
@r###"
fn active_param_type_match() {
mark::check!(active_param_type_match);
check(
r#"
struct S { foo: i64, bar: u32, baz: () }
fn test(x: u32) { }
fn foo(s: S) { test(s.<|>) }
"#,
expect![[r#"
[
CompletionItem {
label: "another_field",
source_range: 136..136,
delete: 136..136,
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "my_string",
source_range: 136..136,
delete: 136..136,
insert: "my_string",
kind: Field,
detail: "{unknown}",
},
CompletionItem {
label: "the_field",
source_range: 136..136,
delete: 136..136,
insert: "the_field",
label: "bar",
source_range: 83..83,
delete: 83..83,
insert: "bar",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "baz",
source_range: 83..83,
delete: 83..83,
insert: "baz",
kind: Field,
detail: "()",
},
CompletionItem {
label: "foo",
source_range: 83..83,
delete: 83..83,
insert: "foo",
kind: Field,
detail: "i64",
},
]
"###
"#]],
);
}
#[test]
fn test_struct_field_completion_in_func_call_with_type_and_name() {
assert_debug_snapshot!(
do_reference_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
fn test(the_field: u32) -> u32 { the_field }
fn foo(a: A) {
test(a.<|>)
}
",
),
@r###"
fn active_param_type_and_name_match() {
check(
r#"
struct S { foo: i64, bar: u32, baz: u32 }
fn test(bar: u32) { }
fn foo(s: S) { test(s.<|>) }
"#,
expect![[r#"
[
CompletionItem {
label: "another_field",
source_range: 143..143,
delete: 143..143,
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: 143..143,
delete: 143..143,
insert: "another_good_type",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: 143..143,
delete: 143..143,
insert: "the_field",
label: "bar",
source_range: 86..86,
delete: 86..86,
insert: "bar",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
]
"###
);
}
#[test]
fn test_struct_field_completion_in_record_lit() {
mark::check!(test_struct_field_completion_in_record_lit);
assert_debug_snapshot!(
do_reference_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn foo(a: A) {
let b = B {
the_field: a.<|>
};
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: 189..189,
delete: 189..189,
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: 189..189,
delete: 189..189,
insert: "another_good_type",
label: "baz",
source_range: 86..86,
delete: 86..86,
insert: "baz",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: 189..189,
delete: 189..189,
insert: "the_field",
label: "foo",
source_range: 86..86,
delete: 86..86,
insert: "foo",
kind: Field,
detail: "i64",
},
]
"#]],
);
}
#[test]
fn record_field_type_match() {
mark::check!(record_field_type_match);
check(
r#"
struct A { foo: i64, bar: u32, baz: u32 }
struct B { x: (), y: f32, bar: u32 }
fn foo(a: A) { B { bar: a.<|> }; }
"#,
expect![[r#"
[
CompletionItem {
label: "bar",
source_range: 105..105,
delete: 105..105,
insert: "bar",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
]
"###
);
}
#[test]
fn test_struct_field_completion_in_record_lit_and_fn_call() {
assert_debug_snapshot!(
do_reference_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn test(the_field: i64) -> i64 { the_field }
fn foo(a: A) {
let b = B {
the_field: test(a.<|>)
};
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: 239..239,
delete: 239..239,
insert: "another_field",
kind: Field,
detail: "i64",
score: TypeMatch,
},
CompletionItem {
label: "another_good_type",
source_range: 239..239,
delete: 239..239,
insert: "another_good_type",
kind: Field,
detail: "u32",
},
CompletionItem {
label: "the_field",
source_range: 239..239,
delete: 239..239,
insert: "the_field",
kind: Field,
detail: "u32",
},
]
"###
);
}
#[test]
fn test_struct_field_completion_in_fn_call_and_record_lit() {
assert_debug_snapshot!(
do_reference_completion(
r"
struct A { another_field: i64, another_good_type: u32, the_field: u32 }
struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 }
fn test(the_field: i64) -> i64 { the_field }
fn foo(a: A) {
test(B {
the_field: a.<|>
});
}
",
),
@r###"
[
CompletionItem {
label: "another_field",
source_range: 231..231,
delete: 231..231,
insert: "another_field",
kind: Field,
detail: "i64",
},
CompletionItem {
label: "another_good_type",
source_range: 231..231,
delete: 231..231,
insert: "another_good_type",
label: "baz",
source_range: 105..105,
delete: 105..105,
insert: "baz",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "the_field",
source_range: 231..231,
delete: 231..231,
insert: "the_field",
label: "foo",
source_range: 105..105,
delete: 105..105,
insert: "foo",
kind: Field,
detail: "i64",
},
]
"#]],
)
}
#[test]
fn record_field_type_match_and_fn_call() {
check(
r#"
struct A { foo: i64, bar: u32, baz: u32 }
struct B { x: (), y: f32, bar: u32 }
fn f(foo: i64) { }
fn foo(a: A) { B { bar: f(a.<|>) }; }
"#,
expect![[r#"
[
CompletionItem {
label: "bar",
source_range: 127..127,
delete: 127..127,
insert: "bar",
kind: Field,
detail: "u32",
},
CompletionItem {
label: "baz",
source_range: 127..127,
delete: 127..127,
insert: "baz",
kind: Field,
detail: "u32",
},
CompletionItem {
label: "foo",
source_range: 127..127,
delete: 127..127,
insert: "foo",
kind: Field,
detail: "i64",
score: TypeAndNameMatch,
},
]
"#]],
);
check(
r#"
struct A { foo: i64, bar: u32, baz: u32 }
struct B { x: (), y: f32, bar: u32 }
fn f(foo: i64) { }
fn foo(a: A) { f(B { bar: a.<|> }); }
"#,
expect![[r#"
[
CompletionItem {
label: "bar",
source_range: 127..127,
delete: 127..127,
insert: "bar",
kind: Field,
detail: "u32",
score: TypeAndNameMatch,
},
CompletionItem {
label: "baz",
source_range: 127..127,
delete: 127..127,
insert: "baz",
kind: Field,
detail: "u32",
score: TypeMatch,
},
CompletionItem {
label: "foo",
source_range: 127..127,
delete: 127..127,
insert: "foo",
kind: Field,
detail: "i64",
},
]
"###
"#]],
);
}
#[test]
fn prioritize_exact_ref_match() {
assert_debug_snapshot!(
do_reference_completion(
r"
struct WorldSnapshot { _f: () };
fn go(world: &WorldSnapshot) {
go(w<|>)
}
",
),
@r###"
check(
r#"
struct WorldSnapshot { _f: () };
fn go(world: &WorldSnapshot) { go(w<|>) }
"#,
expect![[r#"
[
CompletionItem {
label: "WorldSnapshot",
source_range: 71..72,
delete: 71..72,
source_range: 67..68,
delete: 67..68,
insert: "WorldSnapshot",
kind: Struct,
},
CompletionItem {
label: "go(…)",
source_range: 71..72,
delete: 71..72,
source_range: 67..68,
delete: 67..68,
insert: "go(${1:world})$0",
kind: Function,
lookup: "go",
@ -1185,15 +1132,15 @@ fn main() { frobnicate!(); }
},
CompletionItem {
label: "world",
source_range: 71..72,
delete: 71..72,
source_range: 67..68,
delete: 67..68,
insert: "world",
kind: Binding,
detail: "&WorldSnapshot",
score: TypeAndNameMatch,
},
]
"###
"#]],
);
}
}