Repository: rust-analyzer/rust-analyzer
Pull request #5219 (2020-07-04 08:37:23)

Cleanup dot completiont tests


bors r+
🤖


Patch:
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index ee4e24fcab..667a8b9499 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -1,17 +1,12 @@
-//! FIXME: write short doc here
+//! Completes references after dot (fields and method calls).
 
 use hir::{HasVisibility, Type};
-
-use crate::{
-    completion::{
-        completion_context::CompletionContext,
-        completion_item::{CompletionKind, Completions},
-    },
-    CompletionItem,
-};
 use rustc_hash::FxHashSet;
+use test_utils::mark;
 
-/// Complete dot accesses, i.e. fields or methods (and .await syntax).
+use crate::completion::{completion_context::CompletionContext, completion_item::Completions};
+
+/// Complete dot accesses, i.e. fields or methods.
 pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
     let dot_receiver = match &ctx.dot_receiver {
         Some(expr) => expr,
@@ -23,18 +18,12 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
         _ => return,
     };
 
-    if !ctx.is_call {
+    if ctx.is_call {
+        mark::hit!(test_no_struct_field_completion_for_method_call);
+    } else {
         complete_fields(acc, ctx, &receiver_ty);
     }
     complete_methods(acc, ctx, &receiver_ty);
-
-    // Suggest .await syntax for types that implement Future trait
-    if receiver_ty.impls_future(ctx.db) {
-        CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
-            .detail("expr.await")
-            .insert_text("await")
-            .add_to(acc);
-    }
 }
 
 fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
@@ -72,801 +61,356 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
 
 #[cfg(test)]
 mod tests {
-    use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
-    use insta::assert_debug_snapshot;
+    use expect::{expect, Expect};
+    use test_utils::mark;
+
+    use crate::completion::{test_utils::completion_list, CompletionKind};
 
-    fn do_ref_completion(code: &str) -> Vec<CompletionItem> {
-        do_completion(code, CompletionKind::Reference)
+    fn check(ra_fixture: &str, expect: Expect) {
+        let actual = completion_list(ra_fixture, CompletionKind::Reference);
+        expect.assert_eq(&actual);
     }
 
     #[test]
-    fn test_struct_field_completion() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-                r"
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                a.<|>
-                }
-                ",
-        ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 45..45,
-                delete: 45..45,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+    fn test_struct_field_and_method_completion() {
+        check(
+            r#"
+struct S { foo: u32 }
+impl S {
+    fn bar(&self) {}
+}
+fn foo(s: S) { s.<|> }
+"#,
+            expect![[r#"
+                me bar() fn bar(&self)
+                fd foo u32
+            "#]],
         );
     }
 
     #[test]
     fn test_struct_field_completion_self() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A {
-                /// This is the_field
-                the_field: (u32,)
-            }
-            impl A {
-                fn foo(self) {
-                    self.<|>
-                }
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "foo()",
-                source_range: 102..102,
-                delete: 102..102,
-                insert: "foo()$0",
-                kind: Method,
-                lookup: "foo",
-                detail: "fn foo(self)",
-            },
-            CompletionItem {
-                label: "the_field",
-                source_range: 102..102,
-                delete: 102..102,
-                insert: "the_field",
-                kind: Field,
-                detail: "(u32,)",
-                documentation: Documentation(
-                    "This is the_field",
-                ),
-            },
-        ]
-        "###
-        );
+        check(
+            r#"
+struct S { the_field: (u32,) }
+impl S {
+    fn foo(self) { self.<|> }
+}
+"#,
+            expect![[r#"
+                me foo() fn foo(self)
+                fd the_field (u32,)
+            "#]],
+        )
     }
 
     #[test]
     fn test_struct_field_completion_autoderef() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A { the_field: (u32, i32) }
-            impl A {
-                fn foo(&self) {
-                    self.<|>
-                }
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "foo()",
-                source_range: 77..77,
-                delete: 77..77,
-                insert: "foo()$0",
-                kind: Method,
-                lookup: "foo",
-                detail: "fn foo(&self)",
-            },
-            CompletionItem {
-                label: "the_field",
-                source_range: 77..77,
-                delete: 77..77,
-                insert: "the_field",
-                kind: Field,
-                detail: "(u32, i32)",
-            },
-        ]
-        "###
-        );
+        check(
+            r#"
+struct A { the_field: (u32, i32) }
+impl A {
+    fn foo(&self) { self.<|> }
+}
+"#,
+            expect![[r#"
+                me foo() fn foo(&self)
+                fd the_field (u32, i32)
+            "#]],
+        )
     }
 
     #[test]
     fn test_no_struct_field_completion_for_method_call() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A { the_field: u32 }
-            fn foo(a: A) {
-               a.<|>()
-            }
-            ",
-        ),
-        @"[]"
+        mark::check!(test_no_struct_field_completion_for_method_call);
+        check(
+            r#"
+struct A { the_field: u32 }
+fn foo(a: A) { a.<|>() }
+"#,
+            expect![[""]],
         );
     }
 
     #[test]
-    fn test_struct_field_visibility_private() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            mod inner {
-                struct A {
-                    private_field: u32,
-                    pub pub_field: u32,
-                    pub(crate) crate_field: u32,
-                    pub(super) super_field: u32,
-                }
-            }
-            fn foo(a: inner::A) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "crate_field",
-                source_range: 192..192,
-                delete: 192..192,
-                insert: "crate_field",
-                kind: Field,
-                detail: "u32",
-            },
-            CompletionItem {
-                label: "pub_field",
-                source_range: 192..192,
-                delete: 192..192,
-                insert: "pub_field",
-                kind: Field,
-                detail: "u32",
-            },
-            CompletionItem {
-                label: "super_field",
-                source_range: 192..192,
-                delete: 192..192,
-                insert: "super_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
-        );
+    fn test_visibility_filtering() {
+        check(
+            r#"
+mod inner {
+    pub struct A {
+        private_field: u32,
+        pub pub_field: u32,
+        pub(crate) crate_field: u32,
+        pub(super) super_field: u32,
     }
-
-    #[test]
-    fn test_union_field_completion() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            union Un {
-                field: u8,
-                other: u16,
-            }
-
-            fn foo(u: Un) {
-                u.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "field",
-                source_range: 67..67,
-                delete: 67..67,
-                insert: "field",
-                kind: Field,
-                detail: "u8",
-            },
-            CompletionItem {
-                label: "other",
-                source_range: 67..67,
-                delete: 67..67,
-                insert: "other",
-                kind: Field,
-                detail: "u16",
-            },
-        ]
-        "###
+}
+fn foo(a: inner::A) { a.<|> }
+"#,
+            expect![[r#"
+                fd crate_field u32
+                fd pub_field u32
+                fd super_field u32
+            "#]],
         );
-    }
 
-    #[test]
-    fn test_method_completion() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A {}
-            impl A {
-                fn the_method(&self) {}
-            }
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 71..71,
-                delete: 71..71,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
+        check(
+            r#"
+struct A {}
+mod m {
+    impl super::A {
+        fn private_method(&self) {}
+        pub(super) fn the_method(&self) {}
+    }
+}
+fn foo(a: A) { a.<|> }
+"#,
+            expect![[r#"
+                me the_method() pub(super) fn the_method(&self)
+            "#]],
         );
     }
 
     #[test]
-    fn test_method_completion_only_fitting_impls() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct A<T> {}
-            impl A<u32> {
-                fn the_method(&self) {}
-            }
-            impl A<i32> {
-                fn the_other_method(&self) {}
-            }
-            fn foo(a: A<u32>) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 134..134,
-                delete: 134..134,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
+    fn test_union_field_completion() {
+        check(
+            r#"
+union U { field: u8, other: u16 }
+fn foo(u: U) { u.<|> }
+"#,
+            expect![[r#"
+                fd field u8
+                fd other u16
+            "#]],
         );
     }
 
     #[test]
-    fn test_method_completion_private() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct A {}
-            mod m {
-                impl super::A {
-                    fn private_method(&self) {}
-                    pub(super) fn the_method(&self) {}
-                }
-            }
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 147..147,
-                delete: 147..147,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "pub(super) fn the_method(&self)",
-            },
-        ]
-        "###
-        );
+    fn test_method_completion_only_fitting_impls() {
+        check(
+            r#"
+struct A<T> {}
+impl A<u32> {
+    fn the_method(&self) {}
+}
+impl A<i32> {
+    fn the_other_method(&self) {}
+}
+fn foo(a: A<u32>) { a.<|> }
+"#,
+            expect![[r#"
+                me the_method() fn the_method(&self)
+            "#]],
+        )
     }
 
     #[test]
     fn test_trait_method_completion() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct A {}
-            trait Trait { fn the_method(&self); }
-            impl Trait for A {}
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 90..90,
-                delete: 90..90,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
+        check(
+            r#"
+struct A {}
+trait Trait { fn the_method(&self); }
+impl Trait for A {}
+fn foo(a: A) { a.<|> }
+"#,
+            expect![[r#"
+                me the_method() fn the_method(&self)
+            "#]],
         );
     }
 
     #[test]
     fn test_trait_method_completion_deduplicated() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct A {}
-            trait Trait { fn the_method(&self); }
-            impl<T> Trait for T {}
-            fn foo(a: &A) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 94..94,
-                delete: 94..94,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
+        check(
+            r"
+struct A {}
+trait Trait { fn the_method(&self); }
+impl<T> Trait for T {}
+fn foo(a: &A) { a.<|> }
+",
+            expect![[r#"
+                me the_method() fn the_method(&self)
+            "#]],
         );
     }
 
     #[test]
     fn completes_trait_method_from_other_module() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct A {}
-            mod m {
-                pub trait Trait { fn the_method(&self); }
-            }
-            use m::Trait;
-            impl Trait for A {}
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 122..122,
-                delete: 122..122,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
-        );
-    }
-
-    #[test]
-    fn test_no_non_self_method() {
-        assert_debug_snapshot!(
-        do_ref_completion(
+        check(
             r"
-            struct A {}
-            impl A {
-                fn the_method() {}
-            }
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-        ),
-        @"[]"
+struct A {}
+mod m {
+    pub trait Trait { fn the_method(&self); }
+}
+use m::Trait;
+impl Trait for A {}
+fn foo(a: A) { a.<|> }
+",
+            expect![[r#"
+                me the_method() fn the_method(&self)
+            "#]],
         );
     }
 
     #[test]
-    fn test_method_attr_filtering() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A {}
-            impl A {
-                #[inline]
-                fn the_method(&self) {
-                    let x = 1;
-                    let y = 2;
-                }
-            }
-            fn foo(a: A) {
-               a.<|>
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 128..128,
-                delete: 128..128,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "fn the_method(&self)",
-            },
-        ]
-        "###
+    fn test_no_non_self_method() {
+        check(
+            r#"
+struct A {}
+impl A {
+    fn the_method() {}
+}
+fn foo(a: A) {
+   a.<|>
+}
+"#,
+            expect![[""]],
         );
     }
 
     #[test]
     fn test_tuple_field_completion() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            fn foo() {
-               let b = (0, 3.14);
-               b.<|>
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "0",
-                source_range: 38..38,
-                delete: 38..38,
-                insert: "0",
-                kind: Field,
-                detail: "i32",
-            },
-            CompletionItem {
-                label: "1",
-                source_range: 38..38,
-                delete: 38..38,
-                insert: "1",
-                kind: Field,
-                detail: "f64",
-            },
-        ]
-        "###
-        );
+        check(
+            r#"
+fn foo() {
+   let b = (0, 3.14);
+   b.<|>
+}
+"#,
+            expect![[r#"
+                fd 0 i32
+                fd 1 f64
+            "#]],
+        )
     }
 
     #[test]
     fn test_tuple_field_inference() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            pub struct S;
-            impl S {
-                pub fn blah(&self) {}
-            }
+        check(
+            r#"
+pub struct S;
+impl S { pub fn blah(&self) {} }
 
-            struct T(S);
+struct T(S);
 
-            impl T {
-                fn foo(&self) {
-                    // FIXME: This doesn't work without the trailing `a` as `0.` is a float
-                    self.0.a<|>
-                }
-            }
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "blah()",
-                source_range: 190..191,
-                delete: 190..191,
-                insert: "blah()$0",
-                kind: Method,
-                lookup: "blah",
-                detail: "pub fn blah(&self)",
-            },
-        ]
-        "###
-        );
+impl T {
+    fn foo(&self) {
+        // FIXME: This doesn't work without the trailing `a` as `0.` is a float
+        self.0.a<|>
     }
-
-    #[test]
-    fn test_completion_works_in_consts() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-            r"
-            struct A { the_field: u32 }
-            const X: u32 = {
-                A { the_field: 92 }.<|>
-            };
-            ",
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 69..69,
-                delete: 69..69,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+}
+"#,
+            expect![[r#"
+                me blah() pub fn blah(&self)
+            "#]],
         );
     }
 
     #[test]
-    fn test_completion_await_impls_future() {
-        assert_debug_snapshot!(
-        do_completion(
-            r###"
-            //- /main.rs
-            use std::future::*;
-            struct A {}
-            impl Future for A {}
-            fn foo(a: A) {
-                a.<|>
-            }
-
-            //- /std/lib.rs
-            pub mod future {
-                #[lang = "future_trait"]
-                pub trait Future {}
-            }
-            "###, CompletionKind::Keyword),
-        @r###"
-        [
-            CompletionItem {
-                label: "await",
-                source_range: 74..74,
-                delete: 74..74,
-                insert: "await",
-                detail: "expr.await",
-            },
-        ]
-        "###
-        )
-    }
-
-    #[test]
-    fn test_super_super_completion() {
-        assert_debug_snapshot!(
-        do_ref_completion(
-                r"
-                mod a {
-                    const A: usize = 0;
-
-                    mod b {
-                        const B: usize = 0;
-
-                        mod c {
-                            use super::super::<|>
-                        }
-                    }
-                }
-                ",
-        ),
-            @r###"
-        [
-            CompletionItem {
-                label: "A",
-                source_range: 120..120,
-                delete: 120..120,
-                insert: "A",
-                kind: Const,
-            },
-            CompletionItem {
-                label: "b",
-                source_range: 120..120,
-                delete: 120..120,
-                insert: "b",
-                kind: Module,
-            },
-        ]
-        "###
+    fn test_completion_works_in_consts() {
+        check(
+            r#"
+struct A { the_field: u32 }
+const X: u32 = {
+    A { the_field: 92 }.<|>
+};
+"#,
+            expect![[r#"
+                fd the_field u32
+            "#]],
         );
     }
 
     #[test]
     fn works_in_simple_macro_1() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-                macro_rules! m { ($e:expr) => { $e } }
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                    m!(a.x<|>)
-                }
-                ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 91..92,
-                delete: 91..92,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
-        );
-    }
-
-    #[test]
-    fn works_in_simple_macro_recursive() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-                macro_rules! m { ($e:expr) => { $e } }
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                    m!(a.x<|>)
-                }
-                ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 91..92,
-                delete: 91..92,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+        check(
+            r#"
+macro_rules! m { ($e:expr) => { $e } }
+struct A { the_field: u32 }
+fn foo(a: A) {
+    m!(a.x<|>)
+}
+"#,
+            expect![[r#"
+                fd the_field u32
+            "#]],
         );
     }
 
     #[test]
     fn works_in_simple_macro_2() {
         // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-                macro_rules! m { ($e:expr) => { $e } }
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                    m!(a.<|>)
-                }
-                ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 91..91,
-                delete: 91..91,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+        check(
+            r#"
+macro_rules! m { ($e:expr) => { $e } }
+struct A { the_field: u32 }
+fn foo(a: A) {
+    m!(a.<|>)
+}
+"#,
+            expect![[r#"
+                fd the_field u32
+            "#]],
         );
     }
 
     #[test]
     fn works_in_simple_macro_recursive_1() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-                macro_rules! m { ($e:expr) => { $e } }
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                    m!(m!(m!(a.x<|>)))
-                }
-                ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 97..98,
-                delete: 97..98,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+        check(
+            r#"
+macro_rules! m { ($e:expr) => { $e } }
+struct A { the_field: u32 }
+fn foo(a: A) {
+    m!(m!(m!(a.x<|>)))
+}
+"#,
+            expect![[r#"
+                fd the_field u32
+            "#]],
         );
     }
 
     #[test]
     fn macro_expansion_resilient() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-                macro_rules! dbg {
-                    () => {};
-                    ($val:expr) => {
-                        match $val { tmp => { tmp } }
-                    };
-                    // Trailing comma with single argument is ignored
-                    ($val:expr,) => { $crate::dbg!($val) };
-                    ($($val:expr),+ $(,)?) => {
-                        ($($crate::dbg!($val)),+,)
-                    };
-                }
-                struct A { the_field: u32 }
-                fn foo(a: A) {
-                    dbg!(a.<|>)
-                }
-                ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 327..327,
-                delete: 327..327,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-            },
-        ]
-        "###
+        check(
+            r#"
+macro_rules! dbg {
+    () => {};
+    ($val:expr) => {
+        match $val { tmp => { tmp } }
+    };
+    // Trailing comma with single argument is ignored
+    ($val:expr,) => { $crate::dbg!($val) };
+    ($($val:expr),+ $(,)?) => {
+        ($($crate::dbg!($val)),+,)
+    };
+}
+struct A { the_field: u32 }
+fn foo(a: A) {
+    dbg!(a.<|>)
+}
+"#,
+            expect![[r#"
+                fd the_field u32
+            "#]],
         );
     }
 
     #[test]
-    fn test_method_completion_3547() {
-        assert_debug_snapshot!(
-            do_ref_completion(
-                r"
-            struct HashSet<T> {}
-            impl<T> HashSet<T> {
-                pub fn the_method(&self) {}
-            }
-            fn foo() {
-                let s: HashSet<_>;
-                s.<|>
-            }
-            ",
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "the_method()",
-                source_range: 116..116,
-                delete: 116..116,
-                insert: "the_method()$0",
-                kind: Method,
-                lookup: "the_method",
-                detail: "pub fn the_method(&self)",
-            },
-        ]
-        "###
+    fn test_method_completion_issue_3547() {
+        check(
+            r#"
+struct HashSet<T> {}
+impl<T> HashSet<T> {
+    pub fn the_method(&self) {}
+}
+fn foo() {
+    let s: HashSet<_>;
+    s.<|>
+}
+"#,
+            expect![[r#"
+                me the_method() pub fn the_method(&self)
+            "#]],
         );
     }
 }
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index 086b917ce8..340d57a49c 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -35,6 +35,19 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
         }
         _ => {}
     }
+
+    // Suggest .await syntax for types that implement Future trait
+    if let Some(receiver) = &ctx.dot_receiver {
+        if let Some(ty) = ctx.sema.type_of_expr(receiver) {
+            if ty.impls_future(ctx.db) {
+                CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
+                    .kind(CompletionItemKind::Keyword)
+                    .detail("expr.await")
+                    .insert_text("await")
+                    .add_to(acc);
+            }
+        };
+    }
 }
 
 pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -490,4 +503,26 @@ Some multi-line comment<|>
             expect![[""]],
         );
     }
+
+    #[test]
+    fn test_completion_await_impls_future() {
+        check(
+            r#"
+//- /main.rs
+use std::future::*;
+struct A {}
+impl Future for A {}
+fn foo(a: A) { a.<|> }
+
+//- /std/lib.rs
+pub mod future {
+    #[lang = "future_trait"]
+    pub trait Future {}
+}
+"#,
+            expect![[r#"
+                kw await expr.await
+            "#]],
+        )
+    }
 }
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index f133ce3cec..a16866cd2d 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -1205,6 +1205,45 @@ mod tests {
         );
     }
 
+    #[test]
+    fn test_super_super_completion() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                r"
+                mod a {
+                    const A: usize = 0;
+
+                    mod b {
+                        const B: usize = 0;
+
+                        mod c {
+                            use super::super::<|>
+                        }
+                    }
+                }
+                ",
+        ),
+            @r###"
+        [
+            CompletionItem {
+                label: "A",
+                source_range: 120..120,
+                delete: 120..120,
+                insert: "A",
+                kind: Const,
+            },
+            CompletionItem {
+                label: "b",
+                source_range: 120..120,
+                delete: 120..120,
+                insert: "b",
+                kind: Module,
+            },
+        ]
+        "###
+        );
+    }
+
     #[test]
     fn completes_reexported_items_under_correct_name() {
         assert_debug_snapshot!(
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 4db371d57f..477d6f6f64 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 fd12673b29..dc391c46bc 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -1,4 +1,5 @@
 //! This modules takes care of rendering various definitions as completion items.
+//! It also handles scoring (sorting) completions.
 
 use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type};
 use ra_syntax::ast::NameOwner;
@@ -330,14 +331,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,174 +462,254 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
 
 #[cfg(test)]
 mod tests {
-    use insta::assert_debug_snapshot;
+    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, CompletionItem, CompletionKind,
+    use crate::{
+        completion::{
+            test_utils::{
+                check_edit, check_edit_with_config, do_completion, get_all_completion_items,
+            },
+            CompletionConfig, CompletionKind,
+        },
+        CompletionScore,
     };
 
-    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);
+    }
+
+    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_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###"
-        [
-            CompletionItem {
-                label: "Foo",
-                source_range: 56..58,
-                delete: 56..58,
-                insert: "Foo",
-                kind: EnumVariant,
-                detail: "{ x: i32, y: i32 }",
-            },
-        ]
-        "###
+fn main() { Foo::Fo<|> }
+"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "Foo",
+                        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###"
-        [
-            CompletionItem {
-                label: "Foo(…)",
-                source_range: 50..52,
-                delete: 50..52,
-                insert: "Foo($0)",
-                kind: EnumVariant,
-                lookup: "Foo",
-                detail: "(i32, i32)",
-                trigger_call_info: true,
-            },
-        ]
-        "###
+fn main() { Foo::Fo<|> }
+"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "Foo(…)",
+                        source_range: 46..48,
+                        delete: 46..48,
+                        insert: "Foo($0)",
+                        kind: EnumVariant,
+                        lookup: "Foo",
+                        detail: "(i32, i32)",
+                        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###"
-        [
-            CompletionItem {
-                label: "Foo",
-                source_range: 39..41,
-                delete: 39..41,
-                insert: "Foo",
-                kind: EnumVariant,
-                detail: "()",
-            },
-        ]
-        "###
+fn main() { Foo::Fo<|> }
+"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "Foo",
+                        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(
-                r#"
-                #[deprecated]
-                fn something_deprecated() {}
-
-                #[deprecated(since = "1.0.0")]
-                fn something_else_deprecated() {}
-
-                fn main() { som<|> }
-                "#,
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "main()",
-                source_range: 122..125,
-                delete: 122..125,
-                insert: "main()$0",
-                kind: Function,
-                lookup: "main",
-                detail: "fn main()",
-            },
-            CompletionItem {
-                label: "something_deprecated()",
-                source_range: 122..125,
-                delete: 122..125,
-                insert: "something_deprecated()$0",
-                kind: Function,
-                lookup: "something_deprecated",
-                detail: "fn something_deprecated()",
-                deprecated: true,
-            },
-            CompletionItem {
-                label: "something_else_deprecated()",
-                source_range: 122..125,
-                delete: 122..125,
-                insert: "something_else_deprecated()$0",
-                kind: Function,
-                lookup: "something_else_deprecated",
-                detail: "fn something_else_deprecated()",
-                deprecated: true,
-            },
-        ]
-        "###
+        check(
+            r#"
+#[deprecated]
+fn something_deprecated() {}
+#[deprecated(since = "1.0.0")]
+fn something_else_deprecated() {}
+
+fn main() { som<|> }
+"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "main()",
+                        source_range: 121..124,
+                        delete: 121..124,
+                        insert: "main()$0",
+                        kind: Function,
+                        lookup: "main",
+                        detail: "fn main()",
+                    },
+                    CompletionItem {
+                        label: "something_deprecated()",
+                        source_range: 121..124,
+                        delete: 121..124,
+                        insert: "something_deprecated()$0",
+                        kind: Function,
+                        lookup: "something_deprecated",
+                        detail: "fn something_deprecated()",
+                        deprecated: true,
+                    },
+                    CompletionItem {
+                        label: "something_else_deprecated()",
+                        source_range: 121..124,
+                        delete: 121..124,
+                        insert: "something_else_deprecated()$0",
+                        kind: Function,
+                        lookup: "something_else_deprecated",
+                        detail: "fn something_else_deprecated()",
+                        deprecated: true,
+                    },
+                ]
+            "#]],
+        );
+
+        check(
+            r#"
+struct A { #[deprecated] the_field: u32 }
+fn foo() { A { the<|> } }
+"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "the_field",
+                        source_range: 57..60,
+                        delete: 57..60,
+                        insert: "the_field",
+                        kind: Field,
+                        detail: "u32",
+                        deprecated: true,
+                    },
+                ]
+            "#]],
         );
+    }
 
-        assert_debug_snapshot!(do_reference_completion(
+    #[test]
+    fn renders_docs() {
+        check(
             r#"
-struct A {
-    #[deprecated]
-    the_field: u32,
+struct S {
+    /// Field docs
+    foo:
 }
-fn foo() {
-   A { the<|> }
+impl S {
+    /// Method docs
+    fn bar(self) { self.<|> }
+}"#,
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "bar()",
+                        source_range: 94..94,
+                        delete: 94..94,
+                        insert: "bar()$0",
+                        kind: Method,
+                        lookup: "bar",
+                        detail: "fn bar(self)",
+                        documentation: Documentation(
+                            "Method docs",
+                        ),
+                    },
+                    CompletionItem {
+                        label: "foo",
+                        source_range: 94..94,
+                        delete: 94..94,
+                        insert: "foo",
+                        kind: Field,
+                        detail: "{unknown}",
+                        documentation: Documentation(
+                            "Field docs",
+                        ),
+                    },
+                ]
+            "#]],
+        )
+    }
+
+    #[test]
+    fn dont_render_attrs() {
+        check(
+            r#"
+struct S;
+impl S {
+    #[inline]
+    fn the_method(&self) { }
 }
+fn foo(s: S) { s.<|> }
 "#,
-        ),
-        @r###"
-        [
-            CompletionItem {
-                label: "the_field",
-                source_range: 69..72,
-                delete: 69..72,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-                deprecated: true,
-            },
-        ]
-        "###);
+            expect![[r#"
+                [
+                    CompletionItem {
+                        label: "the_method()",
+                        source_range: 81..81,
+                        delete: 81..81,
+                        insert: "the_method()$0",
+                        kind: Method,
+                        lookup: "the_method",
+                        detail: "fn the_method(&self)",
+                    },
+                ]
+            "#]],
+        )
     }
 
     #[test]
@@ -844,466 +925,158 @@ fn f(foo: &Foo) { foo.foo(); }
     #[test]
     fn inserts_angle_brackets_for_generics() {
         mark::check!(inserts_angle_brackets_for_generics);
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                struct Vec<T> {}
-                fn foo(xs: Ve<|>)
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "Vec<…>",
-                source_range: 28..30,
-                delete: 28..30,
-                insert: "Vec<$0>",
-                kind: Struct,
-                lookup: "Vec",
-            },
-            CompletionItem {
-                label: "foo(…)",
-                source_range: 28..30,
-                delete: 28..30,
-                insert: "foo(${1:xs})$0",
-                kind: Function,
-                lookup: "foo",
-                detail: "fn foo(xs: Ve)",
-                trigger_call_info: true,
-            },
-        ]
-        "###
+        check_edit(
+            "Vec",
+            r#"
+struct Vec<T> {}
+fn foo(xs: Ve<|>)
+"#,
+            r#"
+struct Vec<T> {}
+fn foo(xs: Vec<$0>)
+"#,
         );
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                type Vec<T> = (T,);
-                fn foo(xs: Ve<|>)
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "Vec<…>",
-                source_range: 31..33,
-                delete: 31..33,
-                insert: "Vec<$0>",
-                kind: TypeAlias,
-                lookup: "Vec",
-            },
-            CompletionItem {
-                label: "foo(…)",
-                source_range: 31..33,
-                delete: 31..33,
-                insert: "foo(${1:xs})$0",
-                kind: Function,
-                lookup: "foo",
-                detail: "fn foo(xs: Ve)",
-                trigger_call_info: true,
-            },
-        ]
-        "###
+        check_edit(
+            "Vec",
+            r#"
+type Vec<T> = (T,);
+fn foo(xs: Ve<|>)
+"#,
+            r#"
+type Vec<T> = (T,);
+fn foo(xs: Vec<$0>)
+"#,
         );
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                struct Vec<T = i128> {}
-                fn foo(xs: Ve<|>)
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "Vec",
-                source_range: 35..37,
-                delete: 35..37,
-                insert: "Vec",
-                kind: Struct,
-            },
-            CompletionItem {
-                label: "foo(…)",
-                source_range: 35..37,
-                delete: 35..37,
-                insert: "foo(${1:xs})$0",
-                kind: Function,
-                lookup: "foo",
-                detail: "fn foo(xs: Ve)",
-                trigger_call_info: true,
-            },
-        ]
-        "###
+        check_edit(
+            "Vec",
+            r#"
+struct Vec<T = i128> {}
+fn foo(xs: Ve<|>)
+"#,
+            r#"
+struct Vec<T = i128> {}
+fn foo(xs: Vec)
+"#,
         );
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                struct Vec<T> {}
-                fn foo(xs: Ve<|><i128>)
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "Vec",
-                source_range: 28..30,
-                delete: 28..30,
-                insert: "Vec",
-                kind: Struct,
-            },
-            CompletionItem {
-                label: "foo(…)",
-                source_range: 28..30,
-                delete: 28..30,
-                insert: "foo(${1:xs})$0",
-                kind: Function,
-                lookup: "foo",
-                detail: "fn foo(xs: Ve<i128>)",
-                trigger_call_info: true,
-            },
-        ]
-        "###
+        check_edit(
+            "Vec",
+            r#"
+struct Vec<T> {}
+fn foo(xs: Ve<|><i128>)
+"#,
+            r#"
+struct Vec<T> {}
+fn foo(xs: Vec<i128>)
+"#,
         );
     }
 
     #[test]
     fn dont_insert_macro_call_parens_unncessary() {
         mark::check!(dont_insert_macro_call_parens_unncessary);
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                //- /main.rs
-                use foo::<|>;
-
-                //- /foo/lib.rs
-                #[macro_export]
-                macro_rules frobnicate {
-                    () => ()
-                }
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "frobnicate!",
-                source_range: 9..9,
-                delete: 9..9,
-                insert: "frobnicate",
-                kind: Macro,
-                detail: "#[macro_export]\nmacro_rules! frobnicate",
-            },
-        ]
-        "###
-        );
-
-        assert_debug_snapshot!(
-            do_reference_completion(
-                r"
-                //- /main.rs
-                macro_rules frobnicate {
-                    () => ()
-                }
-                fn main() {
-                    frob<|>!();
-                }
-                "
-            ),
-            @r###"
-        [
-            CompletionItem {
-                label: "frobnicate!",
-                source_range: 56..60,
-                delete: 56..60,
-                insert: "frobnicate",
-                kind: Macro,
-                detail: "macro_rules! frobnicate",
-            },
-            CompletionItem {
-                label: "main()",
-                source_range: 56..60,
-                delete: 56..60,
-                insert: "main()$0",
-                kind: Function,
-                lookup: "main",
-                detail: "fn main()",
-            },
-        ]
-        "###
+        check_edit(
+            "frobnicate!",
+            r#"
+//- /main.rs
+use foo::<|>;
+//- /foo/lib.rs
+#[macro_export]
+macro_rules frobnicate { () => () }
+"#,
+            r#"
+use foo::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###"
-        [
-            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",
-                kind: Field,
-                detail: "u32",
-                score: TypeMatch,
-            },
-        ]
-        "###
+        check_edit(
+            "frobnicate!",
+            r#"
+macro_rules frobnicate { () => () }
+fn main() { frob<|>!(); }
+"#,
+            r#"
+macro_rules frobnicate { () => () }
+fn main() { frobnicate!(); }
+"#,
         );
     }
 
     #[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###"
-        [
-            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",
-                kind: Field,
-                detail: "u32",
-                score: TypeAndNameMatch,
-            },
-        ]
-        "###
+    fn active_param_score() {
+        mark::check!(active_param_type_match);
+        check_scores(
+            r#"
+struct S { foo: i64, bar: u32, baz: u32 }
+fn test(bar: u32) { }
+fn foo(s: S) { test(s.<|>) }
+"#,
+            expect![[r#"
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
+            "#]],
         );
     }
 
     #[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",
-                kind: Field,
-                detail: "u32",
-                score: TypeMatch,
-            },
-            CompletionItem {
-                label: "the_field",
-                source_range: 189..189,
-                delete: 189..189,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-                score: TypeAndNameMatch,
-            },
-        ]
-        "###
-        );
+    fn record_field_scores() {
+        mark::check!(record_field_type_match);
+        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#"
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
+            "#]],
+        )
     }
 
     #[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",
-            },
-        ]
-        "###
+    fn record_field_and_call_scores() {
+        check_scores(
+            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#"
+                fd foo [type+name]
+                fd bar []
+                fd baz []
+            "#]],
         );
-    }
-
-    #[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",
-                kind: Field,
-                detail: "u32",
-                score: TypeMatch,
-            },
-            CompletionItem {
-                label: "the_field",
-                source_range: 231..231,
-                delete: 231..231,
-                insert: "the_field",
-                kind: Field,
-                detail: "u32",
-                score: TypeAndNameMatch,
-            },
-        ]
-        "###
+        check_scores(
+            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#"
+                fd bar [type+name]
+                fd baz [type]
+                fd foo []
+            "#]],
         );
     }
 
     #[test]
     fn prioritize_exact_ref_match() {
-        assert_debug_snapshot!(
-        do_reference_completion(
-                r"
-                    struct WorldSnapshot { _f: () };
-                    fn go(world: &WorldSnapshot) {
-                        go(w<|>)
-                    }
-                    ",
-        ),
-            @r###"
-        [
-            CompletionItem {
-                label: "WorldSnapshot",
-                source_range: 71..72,
-                delete: 71..72,
-                insert: "WorldSnapshot",
-                kind: Struct,
-            },
-            CompletionItem {
-                label: "go(…)",
-                source_range: 71..72,
-                delete: 71..72,
-                insert: "go(${1:world})$0",
-                kind: Function,
-                lookup: "go",
-                detail: "fn go(world: &WorldSnapshot)",
-                trigger_call_info: true,
-            },
-            CompletionItem {
-                label: "world",
-                source_range: 71..72,
-                delete: 71..72,
-                insert: "world",
-                kind: Binding,
-                detail: "&WorldSnapshot",
-                score: TypeAndNameMatch,
-            },
-        ]
-        "###
+        check_scores(
+            r#"
+struct WorldSnapshot { _f: () };
+fn go(world: &WorldSnapshot) { go(w<|>) }
+"#,
+            expect![[r#"
+                bn world [type+name]
+                st WorldSnapshot []
+                fn go(…) []
+            "#]],
         );
     }
 }


Test patch:
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index 145d36c98b..cbae1da859 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -13,15 +13,15 @@ use crate::{
 };
 
 pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
-    do_completion_with_options(code, kind, &CompletionConfig::default())
+    do_completion_with_config(code, kind, &CompletionConfig::default())
 }
 
-pub(crate) fn do_completion_with_options(
+pub(crate) fn do_completion_with_config(
     code: &str,
     kind: CompletionKind,
-    options: &CompletionConfig,
+    config: &CompletionConfig,
 ) -> Vec<CompletionItem> {
-    let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options)
+    let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config)
         .into_iter()
         .filter(|c| c.completion_kind == kind)
         .collect();
@@ -30,15 +30,15 @@ pub(crate) fn do_completion_with_options(
 }
 
 pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
-    completion_list_with_options(code, kind, &CompletionConfig::default())
+    completion_list_with_config(code, kind, &CompletionConfig::default())
 }
 
-pub(crate) fn completion_list_with_options(
+pub(crate) fn completion_list_with_config(
     code: &str,
     kind: CompletionKind,
-    options: &CompletionConfig,
+    config: &CompletionConfig,
 ) -> String {
-    let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options)
+    let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, config)
         .into_iter()
         .filter(|c| c.completion_kind == kind)
         .collect();
@@ -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()
 }