about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2020-07-04 09:53:54 +0200
committerAleksey Kladov <aleksey.kladov@gmail.com>2020-07-04 09:53:54 +0200
commit5c68dd6b59cd5006a96280217bc88a6e26f90f1f (patch)
treed8dce79c52d266d9a79edfa673b5e315d195d304
parentaaba2300fb14360a00e75da1916b11fd99c0afce (diff)
downloadrust-5c68dd6b59cd5006a96280217bc88a6e26f90f1f.tar.gz
rust-5c68dd6b59cd5006a96280217bc88a6e26f90f1f.zip
Better tests for completion scoring
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs246
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs5
3 files changed, 61 insertions, 192 deletions
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 4db371d57f4..477d6f6f642 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -95,7 +95,7 @@ impl fmt::Debug for CompletionItem {
     }
 }
 
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
 pub enum CompletionScore {
     /// If only type match
     TypeMatch,
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 9ec33a05092..ee810b59f3b 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -461,12 +461,19 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
 
 #[cfg(test)]
 mod tests {
+    use std::cmp::Reverse;
+
     use expect::{expect, Expect};
     use test_utils::mark;
 
-    use crate::completion::{
-        test_utils::{check_edit, check_edit_with_config, do_completion},
-        CompletionConfig, CompletionKind,
+    use crate::{
+        completion::{
+            test_utils::{
+                check_edit, check_edit_with_config, do_completion, get_all_completion_items,
+            },
+            CompletionConfig, CompletionKind,
+        },
+        CompletionScore,
     };
 
     fn check(ra_fixture: &str, expect: Expect) {
@@ -474,6 +481,29 @@ mod tests {
         expect.assert_debug_eq(&actual);
     }
 
+    fn check_scores(ra_fixture: &str, expect: Expect) {
+        fn display_score(score: Option<CompletionScore>) -> &'static str {
+            match score {
+                Some(CompletionScore::TypeMatch) => "[type]",
+                Some(CompletionScore::TypeAndNameMatch) => "[type+name]",
+                None => "[]".into(),
+            }
+        }
+
+        let mut completions = get_all_completion_items(ra_fixture, &CompletionConfig::default());
+        completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
+        let actual = completions
+            .into_iter()
+            .filter(|it| it.completion_kind == CompletionKind::Reference)
+            .map(|it| {
+                let tag = it.kind().unwrap().tag();
+                let score = display_score(it.score());
+                format!("{} {} {}\n", tag, it.label(), score)
+            })
+            .collect::<String>();
+        expect.assert_eq(&actual);
+    }
+
     #[test]
     fn enum_detail_includes_record_fields() {
         check(
@@ -902,132 +932,42 @@ fn main() { frobnicate!(); }
     }
 
     #[test]
-    fn active_param_type_match() {
+    fn active_param_score() {
         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: "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 active_param_type_and_name_match() {
-        check(
+        check_scores(
             r#"
 struct S { foo: i64, bar: u32, baz: u32 }
 fn test(bar: u32) { }
 fn foo(s: S) { test(s.<|>) }
 "#,
             expect![[r#"
-                [
-                    CompletionItem {
-                        label: "bar",
-                        source_range: 86..86,
-                        delete: 86..86,
-                        insert: "bar",
-                        kind: Field,
-                        detail: "u32",
-                        score: TypeAndNameMatch,
-                    },
-                    CompletionItem {
-                        label: "baz",
-                        source_range: 86..86,
-                        delete: 86..86,
-                        insert: "baz",
-                        kind: Field,
-                        detail: "u32",
-                        score: TypeMatch,
-                    },
-                    CompletionItem {
-                        label: "foo",
-                        source_range: 86..86,
-                        delete: 86..86,
-                        insert: "foo",
-                        kind: Field,
-                        detail: "i64",
-                    },
-                ]
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
             "#]],
         );
     }
 
     #[test]
-    fn record_field_type_match() {
+    fn record_field_scores() {
         mark::check!(record_field_type_match);
-        check(
+        check_scores(
             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,
-                    },
-                    CompletionItem {
-                        label: "baz",
-                        source_range: 105..105,
-                        delete: 105..105,
-                        insert: "baz",
-                        kind: Field,
-                        detail: "u32",
-                        score: TypeMatch,
-                    },
-                    CompletionItem {
-                        label: "foo",
-                        source_range: 105..105,
-                        delete: 105..105,
-                        insert: "foo",
-                        kind: Field,
-                        detail: "i64",
-                    },
-                ]
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
             "#]],
         )
     }
 
     #[test]
-    fn record_field_type_match_and_fn_call() {
-        check(
+    fn record_field_and_call_scores() {
+        check_scores(
             r#"
 struct A { foo: i64, bar: u32, baz: u32 }
 struct B { x: (), y: f32, bar: u32 }
@@ -1035,36 +975,12 @@ 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,
-                    },
-                ]
+                fd foo [type+name]
+                fd bar []
+                fd baz []
             "#]],
         );
-        check(
+        check_scores(
             r#"
 struct A { foo: i64, bar: u32, baz: u32 }
 struct B { x: (), y: f32, bar: u32 }
@@ -1072,74 +988,24 @@ 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",
-                    },
-                ]
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
             "#]],
         );
     }
 
     #[test]
     fn prioritize_exact_ref_match() {
-        check(
+        check_scores(
             r#"
 struct WorldSnapshot { _f: () };
 fn go(world: &WorldSnapshot) { go(w<|>) }
 "#,
             expect![[r#"
-                [
-                    CompletionItem {
-                        label: "WorldSnapshot",
-                        source_range: 67..68,
-                        delete: 67..68,
-                        insert: "WorldSnapshot",
-                        kind: Struct,
-                    },
-                    CompletionItem {
-                        label: "go(…)",
-                        source_range: 67..68,
-                        delete: 67..68,
-                        insert: "go(${1:world})$0",
-                        kind: Function,
-                        lookup: "go",
-                        detail: "fn go(world: &WorldSnapshot)",
-                        trigger_call_info: true,
-                    },
-                    CompletionItem {
-                        label: "world",
-                        source_range: 67..68,
-                        delete: 67..68,
-                        insert: "world",
-                        kind: Binding,
-                        detail: "&WorldSnapshot",
-                        score: TypeAndNameMatch,
-                    },
-                ]
+                bn world [type+name]
+                st WorldSnapshot []
+                fn go(…) []
             "#]],
         );
     }
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index 329acdc8b6e..cbae1da859a 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -92,7 +92,10 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
         .unwrap();
 }
 
-fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> {
+pub(crate) fn get_all_completion_items(
+    code: &str,
+    options: &CompletionConfig,
+) -> Vec<CompletionItem> {
     let (analysis, position) = analysis_and_position(code);
     analysis.completions(options, position).unwrap().unwrap().into()
 }