]> git.lizzy.rs Git - rust.git/commitdiff
refactor completions to use TextEdit instead of InsertText
authorgfreezy <gfreezy@gmail.com>
Sat, 19 Jan 2019 14:02:50 +0000 (22:02 +0800)
committergfreezy <gfreezy@gmail.com>
Sat, 19 Jan 2019 14:02:50 +0000 (22:02 +0800)
54 files changed:
crates/ra_ide_api/src/completion.rs
crates/ra_ide_api/src/completion/complete_dot.rs
crates/ra_ide_api/src/completion/complete_fn_param.rs
crates/ra_ide_api/src/completion/complete_keyword.rs
crates/ra_ide_api/src/completion/complete_path.rs
crates/ra_ide_api/src/completion/complete_scope.rs
crates/ra_ide_api/src/completion/complete_snippet.rs
crates/ra_ide_api/src/completion/completion_context.rs
crates/ra_ide_api/src/completion/completion_item.rs
crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__completion_postfix.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__deeply_nested_use_tree.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_in_use_item.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls2.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt1.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt2.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt3.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__nested_use_tree.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_expressions.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_items.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_crate.snap [new file with mode: 0644]
crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_self.snap [new file with mode: 0644]
crates/ra_ide_api/src/lib.rs
crates/ra_lsp_server/src/conv.rs
crates/ra_lsp_server/src/main_loop/handlers.rs

index b03ddd74c0c29fd8cdd27434d54c89579b9f7388..855f5d9640fba99e7d7592bb9d1275ebcae1acc8 100644 (file)
@@ -19,7 +19,7 @@
     },
 };
 
-pub use crate::completion::completion_item::{CompletionItem, InsertText, CompletionItemKind};
+pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, InsertTextFormat};
 
 /// Main entry point for completion. We run completion as a two-phase process.
 ///
@@ -60,15 +60,3 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
 
     Some(acc)
 }
-
-#[cfg(test)]
-fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
-    use crate::mock_analysis::{single_file_with_position, analysis_and_position};
-    let (analysis, position) = if code.contains("//-") {
-        analysis_and_position(code)
-    } else {
-        single_file_with_position(code)
-    };
-    let completions = completions(&analysis.db, position).unwrap();
-    completions.assert_match(expected_completions, kind);
-}
index 473edc50eabe2677de4c917a6827eb5802c6b0a2..aaf739500a97bc697ce53c01659a69a90fad00ce 100644 (file)
@@ -1,6 +1,7 @@
 use hir::{Ty, Def};
 
-use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind};
+use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
+use crate::completion::completion_item::CompletionKind;
 
 /// Complete dot accesses, i.e. fields or methods (currently only fields).
 pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
@@ -30,6 +31,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
                         for field in s.fields(ctx.db) {
                             CompletionItem::new(
                                 CompletionKind::Reference,
+                                ctx,
                                 field.name().to_string(),
                             )
                             .kind(CompletionItemKind::Field)
@@ -43,7 +45,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
             }
             Ty::Tuple(fields) => {
                 for (i, _ty) in fields.iter().enumerate() {
-                    CompletionItem::new(CompletionKind::Reference, i.to_string())
+                    CompletionItem::new(CompletionKind::Reference, ctx, i.to_string())
                         .kind(CompletionItemKind::Field)
                         .add_to(acc);
                 }
@@ -57,7 +59,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
     receiver.iterate_methods(ctx.db, |func| {
         let sig = func.signature(ctx.db);
         if sig.has_self_param() {
-            CompletionItem::new(CompletionKind::Reference, sig.name().to_string())
+            CompletionItem::new(CompletionKind::Reference, ctx, sig.name().to_string())
                 .from_function(ctx, func)
                 .kind(CompletionItemKind::Method)
                 .add_to(acc);
@@ -69,27 +71,29 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
 #[cfg(test)]
 mod tests {
     use crate::completion::*;
+    use crate::completion::completion_item::check_completion;
 
-    fn check_ref_completion(code: &str, expected_completions: &str) {
-        check_completion(code, expected_completions, CompletionKind::Reference);
+    fn check_ref_completion(name: &str, code: &str) {
+        check_completion(name, code, CompletionKind::Reference);
     }
 
     #[test]
     fn test_struct_field_completion() {
         check_ref_completion(
+            "struct_field_completion",
             r"
             struct A { the_field: u32 }
             fn foo(a: A) {
                a.<|>
             }
             ",
-            r#"the_field "u32""#,
         );
     }
 
     #[test]
     fn test_struct_field_completion_self() {
         check_ref_completion(
+            "struct_field_completion_self",
             r"
             struct A { the_field: (u32,) }
             impl A {
@@ -98,14 +102,13 @@ fn foo(self) {
                 }
             }
             ",
-            r#"the_field "(u32,)"
-               foo "foo($0)""#,
         );
     }
 
     #[test]
     fn test_struct_field_completion_autoderef() {
         check_ref_completion(
+            "struct_field_completion_autoderef",
             r"
             struct A { the_field: (u32, i32) }
             impl A {
@@ -114,27 +117,26 @@ fn foo(&self) {
                 }
             }
             ",
-            r#"the_field "(u32, i32)"
-               foo "foo($0)""#,
         );
     }
 
     #[test]
     fn test_no_struct_field_completion_for_method_call() {
         check_ref_completion(
+            "no_struct_field_completion_for_method_call",
             r"
             struct A { the_field: u32 }
             fn foo(a: A) {
                a.<|>()
             }
             ",
-            r#""#,
         );
     }
 
     #[test]
     fn test_method_completion() {
         check_ref_completion(
+            "method_completion",
             r"
             struct A {}
             impl A {
@@ -144,13 +146,13 @@ fn foo(a: A) {
                a.<|>
             }
             ",
-            r#"the_method "the_method($0)""#,
         );
     }
 
     #[test]
     fn test_no_non_self_method() {
         check_ref_completion(
+            "no_non_self_method",
             r"
             struct A {}
             impl A {
@@ -160,7 +162,6 @@ fn foo(a: A) {
                a.<|>
             }
             ",
-            r#""#,
         );
     }
 }
index c1739e47eab5f04673ce5db26bdb28b0ac6fcd1a..e3d1470c2b5fd2ba39c7a03a01c2a92a8c0601a5 100644 (file)
@@ -34,7 +34,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
             }
         })
         .for_each(|(label, lookup)| {
-            CompletionItem::new(CompletionKind::Magic, label)
+            CompletionItem::new(CompletionKind::Magic, ctx, label)
                 .lookup_by(lookup)
                 .add_to(acc)
         });
@@ -56,38 +56,40 @@ fn process<'a, N: ast::FnDefOwner>(
 #[cfg(test)]
 mod tests {
     use crate::completion::*;
+    use crate::completion::completion_item::check_completion;
 
-    fn check_magic_completion(code: &str, expected_completions: &str) {
-        check_completion(code, expected_completions, CompletionKind::Magic);
+    fn check_magic_completion(name: &str, code: &str) {
+        check_completion(name, code, CompletionKind::Magic);
     }
 
     #[test]
     fn test_param_completion_last_param() {
         check_magic_completion(
+            "param_completion_last_param",
             r"
             fn foo(file_id: FileId) {}
             fn bar(file_id: FileId) {}
             fn baz(file<|>) {}
             ",
-            r#"file_id "file_id: FileId""#,
         );
     }
 
     #[test]
     fn test_param_completion_nth_param() {
         check_magic_completion(
+            "param_completion_nth_param",
             r"
             fn foo(file_id: FileId) {}
             fn bar(file_id: FileId) {}
             fn baz(file<|>, x: i32) {}
             ",
-            r#"file_id "file_id: FileId""#,
         );
     }
 
     #[test]
     fn test_param_completion_trait_param() {
         check_magic_completion(
+            "param_completion_trait_param",
             r"
             pub(crate) trait SourceRoot {
                 pub fn contains(&self, file_id: FileId) -> bool;
@@ -96,7 +98,6 @@ pub(crate) trait SourceRoot {
                 pub fn syntax(&self, file<|>)
             }
             ",
-            r#"file_id "file_id: FileId""#,
         );
     }
 }
index d350f06ceb60f2551cff11f6cb8932e040edc925..3fbf3631317becfffa43717c52ad50846190e929 100644 (file)
@@ -11,36 +11,33 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
     // complete keyword "crate" in use stmt
     match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) {
         (Some(_), None) => {
-            CompletionItem::new(CompletionKind::Keyword, "crate")
+            CompletionItem::new(CompletionKind::Keyword, ctx, "crate")
                 .kind(CompletionItemKind::Keyword)
-                .lookup_by("crate")
-                .snippet("crate::")
+                .insert_text("crate::")
                 .add_to(acc);
-            CompletionItem::new(CompletionKind::Keyword, "self")
+            CompletionItem::new(CompletionKind::Keyword, ctx, "self")
                 .kind(CompletionItemKind::Keyword)
-                .lookup_by("self")
                 .add_to(acc);
-            CompletionItem::new(CompletionKind::Keyword, "super")
+            CompletionItem::new(CompletionKind::Keyword, ctx, "super")
                 .kind(CompletionItemKind::Keyword)
-                .lookup_by("super")
+                .insert_text("super::")
                 .add_to(acc);
         }
         (Some(_), Some(_)) => {
-            CompletionItem::new(CompletionKind::Keyword, "self")
+            CompletionItem::new(CompletionKind::Keyword, ctx, "self")
                 .kind(CompletionItemKind::Keyword)
-                .lookup_by("self")
                 .add_to(acc);
-            CompletionItem::new(CompletionKind::Keyword, "super")
+            CompletionItem::new(CompletionKind::Keyword, ctx, "super")
                 .kind(CompletionItemKind::Keyword)
-                .lookup_by("super")
+                .insert_text("super::")
                 .add_to(acc);
         }
         _ => {}
     }
 }
 
-fn keyword(kw: &str, snippet: &str) -> CompletionItem {
-    CompletionItem::new(CompletionKind::Keyword, kw)
+fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem {
+    CompletionItem::new(CompletionKind::Keyword, ctx, kw)
         .kind(CompletionItemKind::Keyword)
         .snippet(snippet)
         .build()
@@ -55,25 +52,25 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
         Some(it) => it,
         None => return,
     };
-    acc.add(keyword("if", "if $0 {}"));
-    acc.add(keyword("match", "match $0 {}"));
-    acc.add(keyword("while", "while $0 {}"));
-    acc.add(keyword("loop", "loop {$0}"));
+    acc.add(keyword(ctx, "if", "if $0 {}"));
+    acc.add(keyword(ctx, "match", "match $0 {}"));
+    acc.add(keyword(ctx, "while", "while $0 {}"));
+    acc.add(keyword(ctx, "loop", "loop {$0}"));
 
     if ctx.after_if {
-        acc.add(keyword("else", "else {$0}"));
-        acc.add(keyword("else if", "else if $0 {}"));
+        acc.add(keyword(ctx, "else", "else {$0}"));
+        acc.add(keyword(ctx, "else if", "else if $0 {}"));
     }
     if is_in_loop_body(ctx.leaf) {
         if ctx.can_be_stmt {
-            acc.add(keyword("continue", "continue;"));
-            acc.add(keyword("break", "break;"));
+            acc.add(keyword(ctx, "continue", "continue;"));
+            acc.add(keyword(ctx, "break", "break;"));
         } else {
-            acc.add(keyword("continue", "continue"));
-            acc.add(keyword("break", "break"));
+            acc.add(keyword(ctx, "continue", "continue"));
+            acc.add(keyword(ctx, "break", "break"));
         }
     }
-    acc.add_all(complete_return(fn_def, ctx.can_be_stmt));
+    acc.add_all(complete_return(ctx, fn_def, ctx.can_be_stmt));
 }
 
 fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
@@ -95,78 +92,69 @@ fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
     false
 }
 
-fn complete_return(fn_def: &ast::FnDef, can_be_stmt: bool) -> Option<CompletionItem> {
+fn complete_return(
+    ctx: &CompletionContext,
+    fn_def: &ast::FnDef,
+    can_be_stmt: bool,
+) -> Option<CompletionItem> {
     let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
         (true, true) => "return $0;",
         (true, false) => "return;",
         (false, true) => "return $0",
         (false, false) => "return",
     };
-    Some(keyword("return", snip))
+    Some(keyword(ctx, "return", snip))
 }
 
 #[cfg(test)]
 mod tests {
-    use crate::completion::{CompletionKind, check_completion};
-    fn check_keyword_completion(code: &str, expected_completions: &str) {
-        check_completion(code, expected_completions, CompletionKind::Keyword);
+    use crate::completion::CompletionKind;
+    use crate::completion::completion_item::check_completion;
+
+    fn check_keyword_completion(name: &str, code: &str) {
+        check_completion(name, code, CompletionKind::Keyword);
     }
 
     #[test]
     fn completes_keywords_in_use_stmt() {
         check_keyword_completion(
+            "keywords_in_use_stmt1",
             r"
             use <|>
             ",
-            r#"
-            crate "crate" "crate::"
-            self "self"
-            super "super"
-            "#,
         );
 
         check_keyword_completion(
+            "keywords_in_use_stmt2",
             r"
             use a::<|>
             ",
-            r#"
-            self "self"
-            super "super"
-            "#,
         );
 
         check_keyword_completion(
+            "keywords_in_use_stmt3",
             r"
             use a::{b, <|>}
             ",
-            r#"
-            self "self"
-            super "super"
-            "#,
         );
     }
 
     #[test]
     fn completes_various_keywords_in_function() {
         check_keyword_completion(
+            "keywords_in_function1",
             r"
             fn quux() {
                 <|>
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return;"
-            "#,
         );
     }
 
     #[test]
     fn completes_else_after_if() {
         check_keyword_completion(
+            "keywords_in_function2",
             r"
             fn quux() {
                 if true {
@@ -174,55 +162,35 @@ fn quux() {
                 } <|>
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            else "else {$0}"
-            else if "else if $0 {}"
-            return "return;"
-            "#,
         );
     }
 
     #[test]
     fn test_completion_return_value() {
         check_keyword_completion(
+            "keywords_in_function3",
             r"
             fn quux() -> i32 {
                 <|>
                 92
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return $0;"
-            "#,
         );
         check_keyword_completion(
+            "keywords_in_function4",
             r"
             fn quux() {
                 <|>
                 92
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return;"
-            "#,
         );
     }
 
     #[test]
     fn dont_add_semi_after_return_if_not_a_statement() {
         check_keyword_completion(
+            "dont_add_semi_after_return_if_not_a_statement",
             r"
             fn quux() -> i32 {
                 match () {
@@ -230,19 +198,13 @@ fn quux() -> i32 {
                 }
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return $0"
-            "#,
         );
     }
 
     #[test]
     fn last_return_in_block_has_semi() {
         check_keyword_completion(
+            "last_return_in_block_has_semi1",
             r"
             fn quux() -> i32 {
                 if condition {
@@ -250,15 +212,9 @@ fn quux() -> i32 {
                 }
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return $0;"
-            "#,
         );
         check_keyword_completion(
+            "last_return_in_block_has_semi2",
             r"
             fn quux() -> i32 {
                 if condition {
@@ -268,54 +224,35 @@ fn quux() -> i32 {
                 x
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return $0;"
-            "#,
         );
     }
 
     #[test]
     fn completes_break_and_continue_in_loops() {
         check_keyword_completion(
+            "completes_break_and_continue_in_loops1",
             r"
             fn quux() -> i32 {
                 loop { <|> }
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            continue "continue;"
-            break "break;"
-            return "return $0;"
-            "#,
         );
+
         // No completion: lambda isolates control flow
         check_keyword_completion(
+            "completes_break_and_continue_in_loops2",
             r"
             fn quux() -> i32 {
                 loop { || { <|> } }
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            return "return $0;"
-            "#,
         );
     }
 
     #[test]
     fn no_semi_after_break_continue_in_expr() {
         check_keyword_completion(
+            "no_semi_after_break_continue_in_expr",
             r"
             fn f() {
                 loop {
@@ -325,15 +262,6 @@ fn f() {
                 }
             }
             ",
-            r#"
-            if "if $0 {}"
-            match "match $0 {}"
-            while "while $0 {}"
-            loop "loop {$0}"
-            continue "continue"
-            break "break"
-            return "return"
-            "#,
         )
     }
 }
index 1eded7658ea9d7c45cd9482604ad211e9d2a1f76..7413c71e80fac08e3002229c18f0c1983f5f83f4 100644 (file)
@@ -15,7 +15,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
         hir::Def::Module(module) => {
             let module_scope = module.scope(ctx.db);
             for (name, res) in module_scope.entries() {
-                CompletionItem::new(CompletionKind::Reference, name.to_string())
+                CompletionItem::new(CompletionKind::Reference, ctx, name.to_string())
                     .from_resolution(ctx, res)
                     .add_to(acc);
             }
@@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
             e.variants(ctx.db)
                 .into_iter()
                 .for_each(|(variant_name, _variant)| {
-                    CompletionItem::new(CompletionKind::Reference, variant_name.to_string())
+                    CompletionItem::new(CompletionKind::Reference, ctx, variant_name.to_string())
                         .kind(CompletionItemKind::EnumVariant)
                         .add_to(acc)
                 });
@@ -35,7 +35,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
 
 #[cfg(test)]
 mod tests {
-    use crate::completion::{CompletionKind, check_completion};
+    use crate::completion::CompletionKind;
+    use crate::completion::completion_item::check_completion;
 
     fn check_reference_completion(code: &str, expected_completions: &str) {
         check_completion(code, expected_completions, CompletionKind::Reference);
@@ -44,6 +45,7 @@ fn check_reference_completion(code: &str, expected_completions: &str) {
     #[test]
     fn completes_use_item_starting_with_self() {
         check_reference_completion(
+            "use_item_starting_with_self",
             r"
             use self::m::<|>;
 
@@ -51,13 +53,13 @@ mod m {
                 struct Bar;
             }
             ",
-            "Bar",
         );
     }
 
     #[test]
     fn completes_use_item_starting_with_crate() {
         check_reference_completion(
+            "use_item_starting_with_crate",
             "
             //- /lib.rs
             mod foo;
@@ -65,13 +67,13 @@ fn completes_use_item_starting_with_crate() {
             //- /foo.rs
             use crate::Sp<|>
             ",
-            "Spam;foo",
         );
     }
 
     #[test]
     fn completes_nested_use_tree() {
         check_reference_completion(
+            "nested_use_tree",
             "
             //- /lib.rs
             mod foo;
@@ -79,13 +81,13 @@ fn completes_nested_use_tree() {
             //- /foo.rs
             use crate::{Sp<|>};
             ",
-            "Spam;foo",
         );
     }
 
     #[test]
     fn completes_deeply_nested_use_tree() {
         check_reference_completion(
+            "deeply_nested_use_tree",
             "
             //- /lib.rs
             mod foo;
@@ -97,37 +99,37 @@ pub mod baz {
             //- /foo.rs
             use crate::{bar::{baz::Sp<|>}};
             ",
-            "Spam",
         );
     }
 
     #[test]
     fn completes_enum_variant() {
         check_reference_completion(
+            "reference_completion",
             "
             //- /lib.rs
             enum E { Foo, Bar(i32) }
             fn foo() { let _ = E::<|> }
             ",
-            "Foo;Bar",
         );
     }
 
     #[test]
     fn dont_render_function_parens_in_use_item() {
         check_reference_completion(
+            "dont_render_function_parens_in_use_item",
             "
             //- /lib.rs
             mod m { pub fn foo() {} }
             use crate::m::f<|>;
             ",
-            "foo",
         )
     }
 
     #[test]
     fn dont_render_function_parens_if_already_call() {
         check_reference_completion(
+            "dont_render_function_parens_if_already_call",
             "
             //- /lib.rs
             fn frobnicate() {}
@@ -135,7 +137,6 @@ fn main() {
                 frob<|>();
             }
             ",
-            "main;frobnicate",
         )
     }
 }
index 4276e47e897aefab2bbd7853100f31285702284b..bb080a341f55115e0736ffb9be7b170fa44f291c 100644 (file)
@@ -1,6 +1,5 @@
 use rustc_hash::FxHashSet;
-use ra_syntax::{AstNode, TextUnit};
-
+use ra_syntax::ast::AstNode;
 use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
 
 pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
@@ -13,7 +12,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
     };
     if let Some(function) = &ctx.function {
         let scopes = function.scopes(ctx.db);
-        complete_fn(acc, &scopes, ctx.offset);
+        complete_fn(acc, &scopes, ctx);
     }
 
     let module_scope = module.scope(ctx.db);
@@ -30,20 +29,24 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
             }
         })
         .for_each(|(name, res)| {
-            CompletionItem::new(CompletionKind::Reference, name.to_string())
+            CompletionItem::new(CompletionKind::Reference, ctx, name.to_string())
                 .from_resolution(ctx, res)
                 .add_to(acc)
         });
 }
 
-fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) {
+fn complete_fn(
+    acc: &mut Completions,
+    scopes: &hir::ScopesWithSyntaxMapping,
+    ctx: &CompletionContext,
+) {
     let mut shadowed = FxHashSet::default();
     scopes
-        .scope_chain_for_offset(offset)
+        .scope_chain_for_offset(ctx.offset)
         .flat_map(|scope| scopes.scopes.entries(scope).iter())
         .filter(|entry| shadowed.insert(entry.name()))
         .for_each(|entry| {
-            CompletionItem::new(CompletionKind::Reference, entry.name().to_string())
+            CompletionItem::new(CompletionKind::Reference, ctx, entry.name().to_string())
                 .kind(CompletionItemKind::Binding)
                 .add_to(acc)
         });
@@ -51,15 +54,17 @@ fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, off
 
 #[cfg(test)]
 mod tests {
-    use crate::completion::{CompletionKind, check_completion};
+    use crate::completion::CompletionKind;
+    use crate::completion::completion_item::check_completion;
 
-    fn check_reference_completion(code: &str, expected_completions: &str) {
-        check_completion(code, expected_completions, CompletionKind::Reference);
+    fn check_reference_completion(name: &str, code: &str) {
+        check_completion(name, code, CompletionKind::Reference);
     }
 
     #[test]
     fn completes_bindings_from_let() {
         check_reference_completion(
+            "bindings_from_let",
             r"
             fn quux(x: i32) {
                 let y = 92;
@@ -67,13 +72,13 @@ fn quux(x: i32) {
                 let z = ();
             }
             ",
-            r#"y;x;quux "quux($0)""#,
         );
     }
 
     #[test]
     fn completes_bindings_from_if_let() {
         check_reference_completion(
+            "bindings_from_if_let",
             r"
             fn quux() {
                 if let Some(x) = foo() {
@@ -85,13 +90,13 @@ fn quux() {
                 }
             }
             ",
-            r#"b;a;quux "quux()$0""#,
         );
     }
 
     #[test]
     fn completes_bindings_from_for() {
         check_reference_completion(
+            "bindings_from_for",
             r"
             fn quux() {
                 for x in &[1, 2, 3] {
@@ -99,13 +104,13 @@ fn quux() {
                 }
             }
             ",
-            r#"x;quux "quux()$0""#,
         );
     }
 
     #[test]
     fn completes_module_items() {
         check_reference_completion(
+            "module_items",
             r"
             struct Foo;
             enum Baz {}
@@ -113,13 +118,13 @@ fn quux() {
                 <|>
             }
             ",
-            r#"quux "quux()$0";Foo;Baz"#,
         );
     }
 
     #[test]
     fn completes_module_items_in_nested_modules() {
         check_reference_completion(
+            "module_items_in_nested_modules",
             r"
             struct Foo;
             mod m {
@@ -127,24 +132,24 @@ mod m {
                 fn quux() { <|> }
             }
             ",
-            r#"quux "quux()$0";Bar"#,
         );
     }
 
     #[test]
     fn completes_return_type() {
         check_reference_completion(
+            "return_type",
             r"
             struct Foo;
             fn x() -> <|>
             ",
-            r#"Foo;x "x()$0""#,
         )
     }
 
     #[test]
     fn dont_show_both_completions_for_shadowing() {
         check_reference_completion(
+            "dont_show_both_completions_for_shadowing",
             r"
             fn foo() -> {
                 let bar = 92;
@@ -154,32 +159,29 @@ fn foo() -> {
                 }
             }
             ",
-            r#"bar;foo "foo()$0""#,
         )
     }
 
     #[test]
     fn completes_self_in_methods() {
-        check_reference_completion(r"impl S { fn foo(&self) { <|> } }", "self")
+        check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }")
     }
 
     #[test]
     fn inserts_parens_for_function_calls() {
         check_reference_completion(
+            "inserts_parens_for_function_calls1",
             r"
             fn no_args() {}
             fn main() { no_<|> }
             ",
-            r#"no_args "no_args()$0"
-               main "main()$0""#,
         );
         check_reference_completion(
+            "inserts_parens_for_function_calls2",
             r"
             fn with_args(x: i32, y: String) {}
             fn main() { with_<|> }
             ",
-            r#"main "main()$0"
-               with_args "with_args($0)""#,
         );
     }
 }
index a495751dda02e4c4a3a2fab4f2481147437eca86..fb94e3674a672705529210fe1bd1ff48aabf9f14 100644 (file)
@@ -1,7 +1,7 @@
 use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionItemKind, CompletionContext, completion_item::Builder};
 
-fn snippet(label: &str, snippet: &str) -> Builder {
-    CompletionItem::new(CompletionKind::Snippet, label)
+fn snippet<'a>(ctx: &'a CompletionContext<'a>, label: &str, snippet: &str) -> Builder<'a> {
+    CompletionItem::new(CompletionKind::Snippet, ctx, label)
         .snippet(snippet)
         .kind(CompletionItemKind::Snippet)
 }
@@ -10,8 +10,8 @@ pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
     if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
         return;
     }
-    snippet("pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
-    snippet("ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
+    snippet(ctx, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
+    snippet(ctx, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
 }
 
 pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
@@ -19,6 +19,7 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
         return;
     }
     snippet(
+        ctx,
         "Test function",
         "\
 #[test]
@@ -29,45 +30,33 @@ fn ${1:feature}() {
     .lookup_by("tfn")
     .add_to(acc);
 
-    snippet("pub(crate)", "pub(crate) $0").add_to(acc);
+    snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc);
 }
 
 #[cfg(test)]
 mod tests {
-    use crate::completion::{CompletionKind, check_completion};
-    fn check_snippet_completion(code: &str, expected_completions: &str) {
-        check_completion(code, expected_completions, CompletionKind::Snippet);
+    use crate::completion::CompletionKind;
+    use crate::completion::completion_item::check_completion;
+
+    fn check_snippet_completion(name: &str, code: &str) {
+        check_completion(name, code, CompletionKind::Snippet);
     }
 
     #[test]
     fn completes_snippets_in_expressions() {
-        check_snippet_completion(
-            r"fn foo(x: i32) { <|> }",
-            r##"
-            pd "eprintln!(\"$0 = {:?}\", $0);"
-            ppd "eprintln!(\"$0 = {:#?}\", $0);"
-            "##,
-        );
+        check_snippet_completion("snippets_in_expressions", r"fn foo(x: i32) { <|> }");
     }
 
     #[test]
     fn completes_snippets_in_items() {
-        // check_snippet_completion(r"
-        //     <|>
-        //     ",
-        //     r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
-        // );
         check_snippet_completion(
+            "snippets_in_items",
             r"
             #[cfg(test)]
             mod tests {
                 <|>
             }
             ",
-            r##"
-            tfn "Test function" "#[test]\nfn ${1:feature}() {\n    $0\n}"
-            pub(crate) "pub(crate) $0"
-            "##,
         );
     }
 }
index e537e0082d84ebfc413c70a78ad2c2959c6f7dd7..de9b95c81f0a990aeee723d95b25492f990afc43 100644 (file)
@@ -12,7 +12,7 @@
 /// `CompletionContext` is created early during completion to figure out, where
 /// exactly is the cursor, syntax-wise.
 #[derive(Debug)]
-pub(super) struct CompletionContext<'a> {
+pub(crate) struct CompletionContext<'a> {
     pub(super) db: &'a db::RootDatabase,
     pub(super) offset: TextUnit,
     pub(super) leaf: &'a SyntaxNode,
@@ -65,6 +65,10 @@ pub(super) fn new(
         Some(ctx)
     }
 
+    pub(crate) fn leaf_range(&self) -> TextRange {
+        self.leaf.range()
+    }
+
     fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
         // Insert a fake ident to get a valid parse tree. We will use this file
         // to determine context, though the original_file will be used for
index 11d00f78cd2b4e0ccab6228e9b6cee65d3d231e7..7bd6344985f311296607998102c87dc16ff8f2e0 100644 (file)
@@ -1,6 +1,10 @@
 use hir::PerNs;
+use ra_text_edit::{
+    AtomTextEdit,
+    TextEdit,
+};
 
-use crate::completion::CompletionContext;
+use crate::completion::completion_context::CompletionContext;
 
 /// `CompletionItem` describes a single completion variant in the editor pop-up.
 /// It is basically a POD with various properties. To construct a
@@ -11,15 +15,29 @@ pub struct CompletionItem {
     /// completion.
     completion_kind: CompletionKind,
     label: String,
+    kind: Option<CompletionItemKind>,
     detail: Option<String>,
     lookup: Option<String>,
-    snippet: Option<String>,
-    kind: Option<CompletionItemKind>,
-}
-
-pub enum InsertText {
-    PlainText { text: String },
-    Snippet { text: String },
+    /// The format of the insert text. The format applies to both the `insert_text` property
+    /// and the `insert` property of a provided `text_edit`.
+    insert_text_format: InsertTextFormat,
+    /// An edit which is applied to a document when selecting this completion. When an edit is
+    /// provided the value of `insert_text` is ignored.
+    ///
+    /// *Note:* The range of the edit must be a single line range and it must contain the position
+    /// at which completion has been requested.
+    ///
+    /// *Note:* If sending a range that overlaps a string, the string should match the relevant
+    /// part of the replacement text, or be filtered out.
+    text_edit: Option<AtomTextEdit>,
+    /// An optional array of additional text edits that are applied when
+    /// selecting this completion. Edits must not overlap (including the same insert position)
+    /// with the main edit nor with themselves.
+    ///
+    /// Additional text edits should be used to change text unrelated to the current cursor position
+    /// (for example adding an import statement at the top of the file if the completion item will
+    /// insert an unqualified type).
+    additional_text_edits: Option<TextEdit>,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -40,7 +58,7 @@ pub enum CompletionItemKind {
     Method,
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub(crate) enum CompletionKind {
     /// Parser-based keyword completion.
     Keyword,
@@ -51,16 +69,30 @@ pub(crate) enum CompletionKind {
     Snippet,
 }
 
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub enum InsertTextFormat {
+    PlainText,
+    Snippet,
+}
+
 impl CompletionItem {
-    pub(crate) fn new(completion_kind: CompletionKind, label: impl Into<String>) -> Builder {
+    pub(crate) fn new<'a>(
+        completion_kind: CompletionKind,
+        ctx: &'a CompletionContext,
+        label: impl Into<String>,
+    ) -> Builder<'a> {
         let label = label.into();
         Builder {
+            ctx,
             completion_kind,
             label,
+            insert_text: None,
+            insert_text_format: InsertTextFormat::PlainText,
             detail: None,
             lookup: None,
-            snippet: None,
             kind: None,
+            text_edit: None,
+            additional_text_edits: None,
         }
     }
     /// What user sees in pop-up in the UI.
@@ -78,64 +110,100 @@ pub fn lookup(&self) -> &str {
             .map(|it| it.as_str())
             .unwrap_or(self.label())
     }
-    /// What is inserted.
-    pub fn insert_text(&self) -> InsertText {
-        match &self.snippet {
-            None => InsertText::PlainText {
-                text: self.label.clone(),
-            },
-            Some(it) => InsertText::Snippet { text: it.clone() },
-        }
+
+    pub fn insert_text_format(&self) -> InsertTextFormat {
+        self.insert_text_format.clone()
     }
 
     pub fn kind(&self) -> Option<CompletionItemKind> {
         self.kind
     }
+    pub fn text_edit(&mut self) -> Option<&AtomTextEdit> {
+        self.text_edit.as_ref()
+    }
+    pub fn take_additional_text_edits(&mut self) -> Option<TextEdit> {
+        self.additional_text_edits.take()
+    }
 }
 
 /// A helper to make `CompletionItem`s.
 #[must_use]
-pub(crate) struct Builder {
+pub(crate) struct Builder<'a> {
+    ctx: &'a CompletionContext<'a>,
     completion_kind: CompletionKind,
     label: String,
+    insert_text: Option<String>,
+    insert_text_format: InsertTextFormat,
     detail: Option<String>,
     lookup: Option<String>,
-    snippet: Option<String>,
     kind: Option<CompletionItemKind>,
+    text_edit: Option<AtomTextEdit>,
+    additional_text_edits: Option<TextEdit>,
 }
 
-impl Builder {
+impl<'a> Builder<'a> {
     pub(crate) fn add_to(self, acc: &mut Completions) {
         acc.add(self.build())
     }
 
     pub(crate) fn build(self) -> CompletionItem {
+        let self_text_edit = self.text_edit;
+        let self_insert_text = self.insert_text;
+        let text_edit = match (self_text_edit, self_insert_text) {
+            (Some(text_edit), ..) => Some(text_edit),
+            (None, Some(insert_text)) => {
+                Some(AtomTextEdit::replace(self.ctx.leaf_range(), insert_text))
+            }
+            _ => None,
+        };
+
         CompletionItem {
             label: self.label,
             detail: self.detail,
+            insert_text_format: self.insert_text_format,
             lookup: self.lookup,
-            snippet: self.snippet,
             kind: self.kind,
             completion_kind: self.completion_kind,
+            text_edit,
+            additional_text_edits: self.additional_text_edits,
         }
     }
-    pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
+    pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder<'a> {
         self.lookup = Some(lookup.into());
         self
     }
-    pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder {
-        self.snippet = Some(snippet.into());
+    pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder<'a> {
+        self.insert_text = Some(insert_text.into());
+        self
+    }
+    pub(crate) fn insert_text_format(
+        mut self,
+        insert_text_format: InsertTextFormat,
+    ) -> Builder<'a> {
+        self.insert_text_format = insert_text_format;
         self
     }
-    pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder {
+    pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder<'a> {
+        self.insert_text_format = InsertTextFormat::Snippet;
+        self.insert_text(snippet)
+    }
+    pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder<'a> {
         self.kind = Some(kind);
         self
     }
+    pub(crate) fn text_edit(mut self, text_edit: AtomTextEdit) -> Builder<'a> {
+        self.text_edit = Some(text_edit);
+        self
+    }
+    pub(crate) fn additional_text_edits(mut self, additional_text_edits: TextEdit) -> Builder<'a> {
+        self.additional_text_edits = Some(additional_text_edits);
+        self
+    }
     #[allow(unused)]
-    pub(crate) fn detail(self, detail: impl Into<String>) -> Builder {
+    pub(crate) fn detail(self, detail: impl Into<String>) -> Builder<'a> {
         self.set_detail(Some(detail))
     }
-    pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
+    pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder<'a> {
         self.detail = detail.map(Into::into);
         self
     }
@@ -143,7 +211,7 @@ pub(super) fn from_resolution(
         mut self,
         ctx: &CompletionContext,
         resolution: &hir::Resolution,
-    ) -> Builder {
+    ) -> Builder<'a> {
         let resolved = resolution.def_id.map(|d| d.resolve(ctx.db));
         let kind = match resolved {
             PerNs {
@@ -188,21 +256,22 @@ pub(super) fn from_function(
         mut self,
         ctx: &CompletionContext,
         function: hir::Function,
-    ) -> Builder {
+    ) -> Builder<'a> {
         // If not an import, add parenthesis automatically.
         if ctx.use_item_syntax.is_none() && !ctx.is_call {
             if function.signature(ctx.db).params().is_empty() {
-                self.snippet = Some(format!("{}()$0", self.label));
+                self.insert_text = Some(format!("{}()$0", self.label));
             } else {
-                self.snippet = Some(format!("{}($0)", self.label));
+                self.insert_text = Some(format!("{}($0)", self.label));
             }
+            self.insert_text_format = InsertTextFormat::Snippet;
         }
         self.kind = Some(CompletionItemKind::Function);
         self
     }
 }
 
-impl Into<CompletionItem> for Builder {
+impl<'a> Into<CompletionItem> for Builder<'a> {
     fn into(self) -> CompletionItem {
         self.build()
     }
@@ -225,60 +294,6 @@ pub(crate) fn add_all<I>(&mut self, items: I)
     {
         items.into_iter().for_each(|item| self.add(item.into()))
     }
-
-    #[cfg(test)]
-    pub(crate) fn assert_match(&self, expected: &str, kind: CompletionKind) {
-        let expected = normalize(expected);
-        let actual = self.debug_render(kind);
-        test_utils::assert_eq_text!(expected.as_str(), actual.as_str(),);
-
-        /// Normalize the textual representation of `Completions`:
-        /// replace `;` with newlines, normalize whitespace
-        fn normalize(expected: &str) -> String {
-            use ra_syntax::{tokenize, TextUnit, TextRange, SyntaxKind::SEMI};
-            let mut res = String::new();
-            for line in expected.trim().lines() {
-                let line = line.trim();
-                let mut start_offset: TextUnit = 0.into();
-                // Yep, we use rust tokenize in completion tests :-)
-                for token in tokenize(line) {
-                    let range = TextRange::offset_len(start_offset, token.len);
-                    start_offset += token.len;
-                    if token.kind == SEMI {
-                        res.push('\n');
-                    } else {
-                        res.push_str(&line[range]);
-                    }
-                }
-
-                res.push('\n');
-            }
-            res
-        }
-    }
-
-    #[cfg(test)]
-    fn debug_render(&self, kind: CompletionKind) -> String {
-        let mut res = String::new();
-        for c in self.buf.iter() {
-            if c.completion_kind == kind {
-                if let Some(lookup) = &c.lookup {
-                    res.push_str(lookup);
-                    res.push_str(&format!(" {:?}", c.label));
-                } else {
-                    res.push_str(&c.label);
-                }
-                if let Some(detail) = &c.detail {
-                    res.push_str(&format!(" {:?}", detail));
-                }
-                if let Some(snippet) = &c.snippet {
-                    res.push_str(&format!(" {:?}", snippet));
-                }
-                res.push('\n');
-            }
-        }
-        res
-    }
 }
 
 impl Into<Vec<CompletionItem>> for Completions {
@@ -286,3 +301,22 @@ fn into(self) -> Vec<CompletionItem> {
         self.buf
     }
 }
+
+#[cfg(test)]
+pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind) {
+    use crate::mock_analysis::{single_file_with_position, analysis_and_position};
+    use crate::completion::completions;
+    use insta::assert_debug_snapshot_matches;
+    let (analysis, position) = if code.contains("//-") {
+        analysis_and_position(code)
+    } else {
+        single_file_with_position(code)
+    };
+    let completions = completions(&analysis.db, position).unwrap();
+    let completion_items: Vec<CompletionItem> = completions.into();
+    let kind_completions: Vec<CompletionItem> = completion_items
+        .into_iter()
+        .filter(|c| c.completion_kind == kind)
+        .collect();
+    assert_debug_snapshot_matches!(test_name, kind_completions);
+}
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap
new file mode 100644 (file)
index 0000000..40a5fd9
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.835266+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "x",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "quux",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "quux()$0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap
new file mode 100644 (file)
index 0000000..f6c0d75
--- /dev/null
@@ -0,0 +1,47 @@
+Created: 2019-01-19T13:42:17.835796+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "b",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "a",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "quux",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [213; 231),
+                insert: "quux()$0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap
new file mode 100644 (file)
index 0000000..a6fda0c
--- /dev/null
@@ -0,0 +1,47 @@
+Created: 2019-01-19T13:42:17.835351+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "y",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "x",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "quux",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [78; 79),
+                insert: "quux($0)"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap
new file mode 100644 (file)
index 0000000..b27674d
--- /dev/null
@@ -0,0 +1,125 @@
+Created: 2019-01-19T13:42:17.819543+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "continue",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "continue;"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "break",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "break;"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [54; 56),
+                insert: "return $0;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap
new file mode 100644 (file)
index 0000000..4ebc168
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.830288+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [59; 61),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [59; 61),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [59; 61),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [59; 61),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [59; 61),
+                insert: "return $0;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completion_postfix.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completion_postfix.snap
new file mode 100644 (file)
index 0000000..60b5a74
--- /dev/null
@@ -0,0 +1,102 @@
+Created: 2019-01-19T13:50:41.824939+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Postfix,
+        label: "not",
+        kind: None,
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [78; 78),
+                insert: "!not"
+            }
+        ),
+        additional_text_edits: Some(
+            TextEdit {
+                atoms: [
+                    AtomTextEdit {
+                        delete: [72; 78),
+                        insert: ""
+                    }
+                ]
+            }
+        )
+    },
+    CompletionItem {
+        completion_kind: Postfix,
+        label: "if",
+        kind: None,
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [78; 78),
+                insert: "if bar {$0}"
+            }
+        ),
+        additional_text_edits: Some(
+            TextEdit {
+                atoms: [
+                    AtomTextEdit {
+                        delete: [72; 78),
+                        insert: ""
+                    }
+                ]
+            }
+        )
+    },
+    CompletionItem {
+        completion_kind: Postfix,
+        label: "match",
+        kind: None,
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [78; 78),
+                insert: "match bar {\n${1:_} => {$0\\},\n}"
+            }
+        ),
+        additional_text_edits: Some(
+            TextEdit {
+                atoms: [
+                    AtomTextEdit {
+                        delete: [72; 78),
+                        insert: ""
+                    }
+                ]
+            }
+        )
+    },
+    CompletionItem {
+        completion_kind: Postfix,
+        label: "while",
+        kind: None,
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [78; 78),
+                insert: "while bar {\n$0\n}"
+            }
+        ),
+        additional_text_edits: Some(
+            TextEdit {
+                atoms: [
+                    AtomTextEdit {
+                        delete: [72; 78),
+                        insert: ""
+                    }
+                ]
+            }
+        )
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__deeply_nested_use_tree.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__deeply_nested_use_tree.snap
new file mode 100644 (file)
index 0000000..b33bc3e
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:53:16.799862+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Spam",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap
new file mode 100644 (file)
index 0000000..0a96291
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.821375+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [84; 102),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [84; 102),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [84; 102),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [84; 102),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [84; 102),
+                insert: "return $0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap
new file mode 100644 (file)
index 0000000..5126c2b
--- /dev/null
@@ -0,0 +1,30 @@
+Created: 2019-01-19T11:53:16.799845+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "main",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "frobnicate",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_in_use_item.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_in_use_item.snap
new file mode 100644 (file)
index 0000000..dd91e33
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:53:16.799820+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap
new file mode 100644 (file)
index 0000000..9c1c3fe
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.841643+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "bar",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [108; 146),
+                insert: "foo()$0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap
new file mode 100644 (file)
index 0000000..7d693be
--- /dev/null
@@ -0,0 +1,40 @@
+Created: 2019-01-19T13:42:17.844671+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "no_args",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [53; 56),
+                insert: "no_args()$0"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "main",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [53; 56),
+                insert: "main()$0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls2.snap
new file mode 100644 (file)
index 0000000..1d2946c
--- /dev/null
@@ -0,0 +1,40 @@
+Created: 2019-01-19T13:42:17.849139+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "main",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [72; 77),
+                insert: "main()$0"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "with_args",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [72; 77),
+                insert: "with_args($0)"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap
new file mode 100644 (file)
index 0000000..2059d63
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.819926+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 54),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 54),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 54),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 54),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 54),
+                insert: "return;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap
new file mode 100644 (file)
index 0000000..2cc8158
--- /dev/null
@@ -0,0 +1,125 @@
+Created: 2019-01-19T13:42:17.819839+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "else",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "else {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "else if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "else if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [91; 105),
+                insert: "return;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap
new file mode 100644 (file)
index 0000000..26dec82
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.822255+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [31; 65),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [31; 65),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [31; 65),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [31; 65),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [31; 65),
+                insert: "return $0;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap
new file mode 100644 (file)
index 0000000..4167165
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.830680+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 58),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 58),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 58),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 58),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [24; 58),
+                insert: "return;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt1.snap
new file mode 100644 (file)
index 0000000..db137d8
--- /dev/null
@@ -0,0 +1,52 @@
+Created: 2019-01-19T13:42:17.819227+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "crate",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [16; 30),
+                insert: "crate::"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "self",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "super",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [16; 30),
+                insert: "super::"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt2.snap
new file mode 100644 (file)
index 0000000..1ff0f49
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.822990+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "self",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "super",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [18; 20),
+                insert: "super::"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt3.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt3.snap
new file mode 100644 (file)
index 0000000..e14bd20
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.826915+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "self",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "super",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [23; 24),
+                insert: "super::"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap
new file mode 100644 (file)
index 0000000..a728283
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.821139+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "return $0;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap
new file mode 100644 (file)
index 0000000..c5d5e74
--- /dev/null
@@ -0,0 +1,91 @@
+Created: 2019-01-19T13:42:17.829078+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [62; 100),
+                insert: "return $0;"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap
new file mode 100644 (file)
index 0000000..c18b44d
--- /dev/null
@@ -0,0 +1,23 @@
+Created: 2019-01-19T13:42:17.817204+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "the_method",
+        kind: Some(
+            Method
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [143; 144),
+                insert: "the_method($0)"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap
new file mode 100644 (file)
index 0000000..8d262a9
--- /dev/null
@@ -0,0 +1,47 @@
+Created: 2019-01-19T13:42:17.835687+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "quux",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [72; 102),
+                insert: "quux()$0"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Foo",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Baz",
+        kind: Some(
+            Enum
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap
new file mode 100644 (file)
index 0000000..0973445
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.836102+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "quux",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [100; 102),
+                insert: "quux()$0"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Bar",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__nested_use_tree.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__nested_use_tree.snap
new file mode 100644 (file)
index 0000000..dbe1e04
--- /dev/null
@@ -0,0 +1,30 @@
+Created: 2019-01-19T11:53:16.799743+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Spam",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Module
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap
new file mode 100644 (file)
index 0000000..417b692
--- /dev/null
@@ -0,0 +1,5 @@
+Created: 2019-01-19T11:34:11.702251+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap
new file mode 100644 (file)
index 0000000..26c5401
--- /dev/null
@@ -0,0 +1,125 @@
+Created: 2019-01-19T13:42:17.821881+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "if",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "if $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "match",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "match $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "while",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "while $0 {}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "loop",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "loop {$0}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "continue",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "continue"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "break",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "break"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Keyword,
+        label: "return",
+        kind: Some(
+            Keyword
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [106; 108),
+                insert: "return"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap
new file mode 100644 (file)
index 0000000..0948c9f
--- /dev/null
@@ -0,0 +1,5 @@
+Created: 2019-01-19T11:34:11.702201+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap
new file mode 100644 (file)
index 0000000..160da9e
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:27:14.070727+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Magic,
+        label: "file_id: FileId",
+        kind: None,
+        detail: None,
+        lookup: Some(
+            "file_id"
+        ),
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap
new file mode 100644 (file)
index 0000000..baeb01e
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:29:09.355053+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Magic,
+        label: "file_id: FileId",
+        kind: None,
+        detail: None,
+        lookup: Some(
+            "file_id"
+        ),
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap
new file mode 100644 (file)
index 0000000..8193c4f
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:29:09.355066+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Magic,
+        label: "file_id: FileId",
+        kind: None,
+        detail: None,
+        lookup: Some(
+            "file_id"
+        ),
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap
new file mode 100644 (file)
index 0000000..abd17dc
--- /dev/null
@@ -0,0 +1,30 @@
+Created: 2019-01-19T11:53:16.799765+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Foo",
+        kind: Some(
+            EnumVariant
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Bar",
+        kind: Some(
+            EnumVariant
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap
new file mode 100644 (file)
index 0000000..c00a5ea
--- /dev/null
@@ -0,0 +1,35 @@
+Created: 2019-01-19T13:42:17.837692+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Foo",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "x",
+        kind: Some(
+            Function
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [46; 60),
+                insert: "x()$0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap
new file mode 100644 (file)
index 0000000..263b151
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:59:18.394156+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "self",
+        kind: Some(
+            Binding
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_expressions.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_expressions.snap
new file mode 100644 (file)
index 0000000..82f0a6d
--- /dev/null
@@ -0,0 +1,40 @@
+Created: 2019-01-19T13:42:17.844708+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Snippet,
+        label: "pd",
+        kind: Some(
+            Snippet
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [16; 18),
+                insert: "eprintln!(\"$0 = {:?}\", $0);"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Snippet,
+        label: "ppd",
+        kind: Some(
+            Snippet
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [16; 18),
+                insert: "eprintln!(\"$0 = {:#?}\", $0);"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_items.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_items.snap
new file mode 100644 (file)
index 0000000..e7cc5c4
--- /dev/null
@@ -0,0 +1,42 @@
+Created: 2019-01-19T13:42:17.845616+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Snippet,
+        label: "Test function",
+        kind: Some(
+            Snippet
+        ),
+        detail: None,
+        lookup: Some(
+            "tfn"
+        ),
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [49; 79),
+                insert: "#[test]\nfn ${1:feature}() {\n    $0\n}"
+            }
+        ),
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Snippet,
+        label: "pub(crate)",
+        kind: Some(
+            Snippet
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [49; 79),
+                insert: "pub(crate) $0"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap
new file mode 100644 (file)
index 0000000..d27ca5f
--- /dev/null
@@ -0,0 +1,20 @@
+Created: 2019-01-19T11:34:11.702218+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "the_field",
+        kind: Some(
+            Field
+        ),
+        detail: Some(
+            "u32"
+        ),
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap
new file mode 100644 (file)
index 0000000..8e547ad
--- /dev/null
@@ -0,0 +1,37 @@
+Created: 2019-01-19T13:42:17.817216+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "the_field",
+        kind: Some(
+            Field
+        ),
+        detail: Some(
+            "(u32, i32)"
+        ),
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Method
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [125; 126),
+                insert: "foo($0)"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap
new file mode 100644 (file)
index 0000000..4536cee
--- /dev/null
@@ -0,0 +1,37 @@
+Created: 2019-01-19T13:42:17.817207+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "the_field",
+        kind: Some(
+            Field
+        ),
+        detail: Some(
+            "(u32,)"
+        ),
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Method
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: Snippet,
+        text_edit: Some(
+            AtomTextEdit {
+                delete: [120; 121),
+                insert: "foo($0)"
+            }
+        ),
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_crate.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_crate.snap
new file mode 100644 (file)
index 0000000..4c35be3
--- /dev/null
@@ -0,0 +1,30 @@
+Created: 2019-01-19T11:53:16.799683+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Spam",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    },
+    CompletionItem {
+        completion_kind: Reference,
+        label: "foo",
+        kind: Some(
+            Module
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_self.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_self.snap
new file mode 100644 (file)
index 0000000..9780d65
--- /dev/null
@@ -0,0 +1,18 @@
+Created: 2019-01-19T11:53:16.799788+00:00
+Creator: insta@0.1.4
+Source: crates/ra_ide_api/src/completion/completion_item.rs
+
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "Bar",
+        kind: Some(
+            Struct
+        ),
+        detail: None,
+        lookup: None,
+        insert_text_format: PlainText,
+        text_edit: None,
+        additional_text_edits: None
+    }
+]
index 33bef178a9a1bcb23b50154d96d15ed29173c700..fb0821ff63827dd90dde9a9998ba3a7c6ccd2508 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 pub use crate::{
-    completion::{CompletionItem, CompletionItemKind, InsertText},
+    completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
     runnables::{Runnable, RunnableKind},
     navigation_target::NavigationTarget,
 };
index 6e187d49e213d92c04041ea79fe6f4ca24923165..76215a97511d152e6034bcb0f295b56ce55ccbf1 100644 (file)
@@ -1,13 +1,13 @@
 use lsp_types::{
-    self, CreateFile, DocumentChangeOperation, DocumentChanges, InsertTextFormat, Location, LocationLink,
+    self, CreateFile, DocumentChangeOperation, DocumentChanges, Location, LocationLink,
     Position, Range, RenameFile, ResourceOp, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
     TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
     WorkspaceEdit,
 };
 use ra_ide_api::{
     CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit,
-    InsertText, NavigationTarget, SourceChange, SourceFileEdit, RangeInfo,
-    LineCol, LineIndex, translate_offset_with_edit
+    NavigationTarget, SourceChange, SourceFileEdit, RangeInfo,
+    LineCol, LineIndex, translate_offset_with_edit, InsertTextFormat
 };
 use ra_syntax::{SyntaxKind, TextRange, TextUnit};
 use ra_text_edit::{AtomTextEdit, TextEdit};
@@ -74,27 +74,30 @@ fn conv(self) -> <Self as Conv>::Output {
     }
 }
 
-impl Conv for CompletionItem {
+impl ConvWith for CompletionItem {
+    type Ctx = LineIndex;
     type Output = ::lsp_types::CompletionItem;
 
-    fn conv(self) -> <Self as Conv>::Output {
-        let mut res = ::lsp_types::CompletionItem {
+    fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem {
+        let text_edit = self.text_edit().map(|t| t.conv_with(ctx));
+        let additonal_text_edit = self
+            .take_additional_text_edits()
+            .map(|it| it.conv_with(ctx));
+
+        let mut res = lsp_types::CompletionItem {
             label: self.label().to_string(),
             detail: self.detail().map(|it| it.to_string()),
             filter_text: Some(self.lookup().to_string()),
             kind: self.kind().map(|it| it.conv()),
+            text_edit,
+            additional_text_edits: additonal_text_edit,
             ..Default::default()
         };
-        match self.insert_text() {
-            InsertText::PlainText { text } => {
-                res.insert_text = Some(text);
-                res.insert_text_format = Some(InsertTextFormat::PlainText);
-            }
-            InsertText::Snippet { text } => {
-                res.insert_text = Some(text);
-                res.insert_text_format = Some(InsertTextFormat::Snippet);
-            }
-        }
+        res.insert_text_format = Some(match self.insert_text_format() {
+            InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
+            InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
+        });
+
         res
     }
 }
index 8f9db68a2f13fff9870ab07c6b0c808d5c0db18d..d1e8c57747b7832b45daf68d3dbd3e8a4f1edb15 100644 (file)
@@ -337,7 +337,11 @@ pub fn handle_completion(
         None => return Ok(None),
         Some(items) => items,
     };
-    let items = items.into_iter().map(|item| item.conv()).collect();
+    let line_index = world.analysis().file_line_index(position.file_id);
+    let items = items
+        .into_iter()
+        .map(|item| item.conv_with(&line_index))
+        .collect();
 
     Ok(Some(req::CompletionResponse::Array(items)))
 }