Skip to content

Commit 5c68dd6

Browse files
committed
Better tests for completion scoring
1 parent aaba230 commit 5c68dd6

File tree

3 files changed

+61
-192
lines changed

3 files changed

+61
-192
lines changed

crates/ra_ide/src/completion/completion_item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl fmt::Debug for CompletionItem {
9595
}
9696
}
9797

98-
#[derive(Debug, Clone, Copy)]
98+
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
9999
pub enum CompletionScore {
100100
/// If only type match
101101
TypeMatch,

crates/ra_ide/src/completion/presentation.rs

Lines changed: 56 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -461,19 +461,49 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
461461

462462
#[cfg(test)]
463463
mod tests {
464+
use std::cmp::Reverse;
465+
464466
use expect::{expect, Expect};
465467
use test_utils::mark;
466468

467-
use crate::completion::{
468-
test_utils::{check_edit, check_edit_with_config, do_completion},
469-
CompletionConfig, CompletionKind,
469+
use crate::{
470+
completion::{
471+
test_utils::{
472+
check_edit, check_edit_with_config, do_completion, get_all_completion_items,
473+
},
474+
CompletionConfig, CompletionKind,
475+
},
476+
CompletionScore,
470477
};
471478

472479
fn check(ra_fixture: &str, expect: Expect) {
473480
let actual = do_completion(ra_fixture, CompletionKind::Reference);
474481
expect.assert_debug_eq(&actual);
475482
}
476483

484+
fn check_scores(ra_fixture: &str, expect: Expect) {
485+
fn display_score(score: Option<CompletionScore>) -> &'static str {
486+
match score {
487+
Some(CompletionScore::TypeMatch) => "[type]",
488+
Some(CompletionScore::TypeAndNameMatch) => "[type+name]",
489+
None => "[]".into(),
490+
}
491+
}
492+
493+
let mut completions = get_all_completion_items(ra_fixture, &CompletionConfig::default());
494+
completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
495+
let actual = completions
496+
.into_iter()
497+
.filter(|it| it.completion_kind == CompletionKind::Reference)
498+
.map(|it| {
499+
let tag = it.kind().unwrap().tag();
500+
let score = display_score(it.score());
501+
format!("{} {} {}\n", tag, it.label(), score)
502+
})
503+
.collect::<String>();
504+
expect.assert_eq(&actual);
505+
}
506+
477507
#[test]
478508
fn enum_detail_includes_record_fields() {
479509
check(
@@ -902,244 +932,80 @@ fn main() { frobnicate!(); }
902932
}
903933

904934
#[test]
905-
fn active_param_type_match() {
935+
fn active_param_score() {
906936
mark::check!(active_param_type_match);
907-
check(
908-
r#"
909-
struct S { foo: i64, bar: u32, baz: () }
910-
fn test(x: u32) { }
911-
fn foo(s: S) { test(s.<|>) }
912-
"#,
913-
expect![[r#"
914-
[
915-
CompletionItem {
916-
label: "bar",
917-
source_range: 83..83,
918-
delete: 83..83,
919-
insert: "bar",
920-
kind: Field,
921-
detail: "u32",
922-
score: TypeMatch,
923-
},
924-
CompletionItem {
925-
label: "baz",
926-
source_range: 83..83,
927-
delete: 83..83,
928-
insert: "baz",
929-
kind: Field,
930-
detail: "()",
931-
},
932-
CompletionItem {
933-
label: "foo",
934-
source_range: 83..83,
935-
delete: 83..83,
936-
insert: "foo",
937-
kind: Field,
938-
detail: "i64",
939-
},
940-
]
941-
"#]],
942-
);
943-
}
944-
945-
#[test]
946-
fn active_param_type_and_name_match() {
947-
check(
937+
check_scores(
948938
r#"
949939
struct S { foo: i64, bar: u32, baz: u32 }
950940
fn test(bar: u32) { }
951941
fn foo(s: S) { test(s.<|>) }
952942
"#,
953943
expect![[r#"
954-
[
955-
CompletionItem {
956-
label: "bar",
957-
source_range: 86..86,
958-
delete: 86..86,
959-
insert: "bar",
960-
kind: Field,
961-
detail: "u32",
962-
score: TypeAndNameMatch,
963-
},
964-
CompletionItem {
965-
label: "baz",
966-
source_range: 86..86,
967-
delete: 86..86,
968-
insert: "baz",
969-
kind: Field,
970-
detail: "u32",
971-
score: TypeMatch,
972-
},
973-
CompletionItem {
974-
label: "foo",
975-
source_range: 86..86,
976-
delete: 86..86,
977-
insert: "foo",
978-
kind: Field,
979-
detail: "i64",
980-
},
981-
]
944+
fd bar [type+name]
945+
fd baz [type]
946+
fd foo []
982947
"#]],
983948
);
984949
}
985950

986951
#[test]
987-
fn record_field_type_match() {
952+
fn record_field_scores() {
988953
mark::check!(record_field_type_match);
989-
check(
954+
check_scores(
990955
r#"
991956
struct A { foo: i64, bar: u32, baz: u32 }
992957
struct B { x: (), y: f32, bar: u32 }
993958
fn foo(a: A) { B { bar: a.<|> }; }
994959
"#,
995960
expect![[r#"
996-
[
997-
CompletionItem {
998-
label: "bar",
999-
source_range: 105..105,
1000-
delete: 105..105,
1001-
insert: "bar",
1002-
kind: Field,
1003-
detail: "u32",
1004-
score: TypeAndNameMatch,
1005-
},
1006-
CompletionItem {
1007-
label: "baz",
1008-
source_range: 105..105,
1009-
delete: 105..105,
1010-
insert: "baz",
1011-
kind: Field,
1012-
detail: "u32",
1013-
score: TypeMatch,
1014-
},
1015-
CompletionItem {
1016-
label: "foo",
1017-
source_range: 105..105,
1018-
delete: 105..105,
1019-
insert: "foo",
1020-
kind: Field,
1021-
detail: "i64",
1022-
},
1023-
]
961+
fd bar [type+name]
962+
fd baz [type]
963+
fd foo []
1024964
"#]],
1025965
)
1026966
}
1027967

1028968
#[test]
1029-
fn record_field_type_match_and_fn_call() {
1030-
check(
969+
fn record_field_and_call_scores() {
970+
check_scores(
1031971
r#"
1032972
struct A { foo: i64, bar: u32, baz: u32 }
1033973
struct B { x: (), y: f32, bar: u32 }
1034974
fn f(foo: i64) { }
1035975
fn foo(a: A) { B { bar: f(a.<|>) }; }
1036976
"#,
1037977
expect![[r#"
1038-
[
1039-
CompletionItem {
1040-
label: "bar",
1041-
source_range: 127..127,
1042-
delete: 127..127,
1043-
insert: "bar",
1044-
kind: Field,
1045-
detail: "u32",
1046-
},
1047-
CompletionItem {
1048-
label: "baz",
1049-
source_range: 127..127,
1050-
delete: 127..127,
1051-
insert: "baz",
1052-
kind: Field,
1053-
detail: "u32",
1054-
},
1055-
CompletionItem {
1056-
label: "foo",
1057-
source_range: 127..127,
1058-
delete: 127..127,
1059-
insert: "foo",
1060-
kind: Field,
1061-
detail: "i64",
1062-
score: TypeAndNameMatch,
1063-
},
1064-
]
978+
fd foo [type+name]
979+
fd bar []
980+
fd baz []
1065981
"#]],
1066982
);
1067-
check(
983+
check_scores(
1068984
r#"
1069985
struct A { foo: i64, bar: u32, baz: u32 }
1070986
struct B { x: (), y: f32, bar: u32 }
1071987
fn f(foo: i64) { }
1072988
fn foo(a: A) { f(B { bar: a.<|> }); }
1073989
"#,
1074990
expect![[r#"
1075-
[
1076-
CompletionItem {
1077-
label: "bar",
1078-
source_range: 127..127,
1079-
delete: 127..127,
1080-
insert: "bar",
1081-
kind: Field,
1082-
detail: "u32",
1083-
score: TypeAndNameMatch,
1084-
},
1085-
CompletionItem {
1086-
label: "baz",
1087-
source_range: 127..127,
1088-
delete: 127..127,
1089-
insert: "baz",
1090-
kind: Field,
1091-
detail: "u32",
1092-
score: TypeMatch,
1093-
},
1094-
CompletionItem {
1095-
label: "foo",
1096-
source_range: 127..127,
1097-
delete: 127..127,
1098-
insert: "foo",
1099-
kind: Field,
1100-
detail: "i64",
1101-
},
1102-
]
991+
fd bar [type+name]
992+
fd baz [type]
993+
fd foo []
1103994
"#]],
1104995
);
1105996
}
1106997

1107998
#[test]
1108999
fn prioritize_exact_ref_match() {
1109-
check(
1000+
check_scores(
11101001
r#"
11111002
struct WorldSnapshot { _f: () };
11121003
fn go(world: &WorldSnapshot) { go(w<|>) }
11131004
"#,
11141005
expect![[r#"
1115-
[
1116-
CompletionItem {
1117-
label: "WorldSnapshot",
1118-
source_range: 67..68,
1119-
delete: 67..68,
1120-
insert: "WorldSnapshot",
1121-
kind: Struct,
1122-
},
1123-
CompletionItem {
1124-
label: "go(…)",
1125-
source_range: 67..68,
1126-
delete: 67..68,
1127-
insert: "go(${1:world})$0",
1128-
kind: Function,
1129-
lookup: "go",
1130-
detail: "fn go(world: &WorldSnapshot)",
1131-
trigger_call_info: true,
1132-
},
1133-
CompletionItem {
1134-
label: "world",
1135-
source_range: 67..68,
1136-
delete: 67..68,
1137-
insert: "world",
1138-
kind: Binding,
1139-
detail: "&WorldSnapshot",
1140-
score: TypeAndNameMatch,
1141-
},
1142-
]
1006+
bn world [type+name]
1007+
st WorldSnapshot []
1008+
fn go(…) []
11431009
"#]],
11441010
);
11451011
}

crates/ra_ide/src/completion/test_utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
9292
.unwrap();
9393
}
9494

95-
fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> {
95+
pub(crate) fn get_all_completion_items(
96+
code: &str,
97+
options: &CompletionConfig,
98+
) -> Vec<CompletionItem> {
9699
let (analysis, position) = analysis_and_position(code);
97100
analysis.completions(options, position).unwrap().unwrap().into()
98101
}

0 commit comments

Comments
 (0)