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