aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide_api/src/completion.rs14
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs27
-rw-r--r--crates/ra_ide_api/src/completion/complete_fn_param.rs13
-rw-r--r--crates/ra_ide_api/src/completion/complete_keyword.rs164
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs21
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs46
-rw-r--r--crates/ra_ide_api/src/completion/complete_snippet.rs37
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs6
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs210
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap47
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap47
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap125
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__completion_postfix.snap102
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__deeply_nested_use_tree.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_in_use_item.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls2.snap40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap125
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt1.snap52
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt2.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt3.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap91
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap23
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap47
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__nested_use_tree.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap5
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap125
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap5
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap35
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap18
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_expressions.snap40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_items.snap42
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap20
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap37
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap37
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_crate.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_self.snap18
-rw-r--r--crates/ra_ide_api/src/lib.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs35
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs6
54 files changed, 2320 insertions, 313 deletions
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index b03ddd74c..855f5d964 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -19,7 +19,7 @@ use crate::{
19 }, 19 },
20}; 20};
21 21
22pub use crate::completion::completion_item::{CompletionItem, InsertText, CompletionItemKind}; 22pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind, InsertTextFormat};
23 23
24/// Main entry point for completion. We run completion as a two-phase process. 24/// Main entry point for completion. We run completion as a two-phase process.
25/// 25///
@@ -60,15 +60,3 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
60 60
61 Some(acc) 61 Some(acc)
62} 62}
63
64#[cfg(test)]
65fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
66 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
67 let (analysis, position) = if code.contains("//-") {
68 analysis_and_position(code)
69 } else {
70 single_file_with_position(code)
71 };
72 let completions = completions(&analysis.db, position).unwrap();
73 completions.assert_match(expected_completions, kind);
74}
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 473edc50e..aaf739500 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -1,6 +1,7 @@
1use hir::{Ty, Def}; 1use hir::{Ty, Def};
2 2
3use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind}; 3use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
4use crate::completion::completion_item::CompletionKind;
4 5
5/// Complete dot accesses, i.e. fields or methods (currently only fields). 6/// Complete dot accesses, i.e. fields or methods (currently only fields).
6pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { 7pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
@@ -30,6 +31,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
30 for field in s.fields(ctx.db) { 31 for field in s.fields(ctx.db) {
31 CompletionItem::new( 32 CompletionItem::new(
32 CompletionKind::Reference, 33 CompletionKind::Reference,
34 ctx,
33 field.name().to_string(), 35 field.name().to_string(),
34 ) 36 )
35 .kind(CompletionItemKind::Field) 37 .kind(CompletionItemKind::Field)
@@ -43,7 +45,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
43 } 45 }
44 Ty::Tuple(fields) => { 46 Ty::Tuple(fields) => {
45 for (i, _ty) in fields.iter().enumerate() { 47 for (i, _ty) in fields.iter().enumerate() {
46 CompletionItem::new(CompletionKind::Reference, i.to_string()) 48 CompletionItem::new(CompletionKind::Reference, ctx, i.to_string())
47 .kind(CompletionItemKind::Field) 49 .kind(CompletionItemKind::Field)
48 .add_to(acc); 50 .add_to(acc);
49 } 51 }
@@ -57,7 +59,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
57 receiver.iterate_methods(ctx.db, |func| { 59 receiver.iterate_methods(ctx.db, |func| {
58 let sig = func.signature(ctx.db); 60 let sig = func.signature(ctx.db);
59 if sig.has_self_param() { 61 if sig.has_self_param() {
60 CompletionItem::new(CompletionKind::Reference, sig.name().to_string()) 62 CompletionItem::new(CompletionKind::Reference, ctx, sig.name().to_string())
61 .from_function(ctx, func) 63 .from_function(ctx, func)
62 .kind(CompletionItemKind::Method) 64 .kind(CompletionItemKind::Method)
63 .add_to(acc); 65 .add_to(acc);
@@ -69,27 +71,29 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty
69#[cfg(test)] 71#[cfg(test)]
70mod tests { 72mod tests {
71 use crate::completion::*; 73 use crate::completion::*;
74 use crate::completion::completion_item::check_completion;
72 75
73 fn check_ref_completion(code: &str, expected_completions: &str) { 76 fn check_ref_completion(name: &str, code: &str) {
74 check_completion(code, expected_completions, CompletionKind::Reference); 77 check_completion(name, code, CompletionKind::Reference);
75 } 78 }
76 79
77 #[test] 80 #[test]
78 fn test_struct_field_completion() { 81 fn test_struct_field_completion() {
79 check_ref_completion( 82 check_ref_completion(
83 "struct_field_completion",
80 r" 84 r"
81 struct A { the_field: u32 } 85 struct A { the_field: u32 }
82 fn foo(a: A) { 86 fn foo(a: A) {
83 a.<|> 87 a.<|>
84 } 88 }
85 ", 89 ",
86 r#"the_field "u32""#,
87 ); 90 );
88 } 91 }
89 92
90 #[test] 93 #[test]
91 fn test_struct_field_completion_self() { 94 fn test_struct_field_completion_self() {
92 check_ref_completion( 95 check_ref_completion(
96 "struct_field_completion_self",
93 r" 97 r"
94 struct A { the_field: (u32,) } 98 struct A { the_field: (u32,) }
95 impl A { 99 impl A {
@@ -98,14 +102,13 @@ mod tests {
98 } 102 }
99 } 103 }
100 ", 104 ",
101 r#"the_field "(u32,)"
102 foo "foo($0)""#,
103 ); 105 );
104 } 106 }
105 107
106 #[test] 108 #[test]
107 fn test_struct_field_completion_autoderef() { 109 fn test_struct_field_completion_autoderef() {
108 check_ref_completion( 110 check_ref_completion(
111 "struct_field_completion_autoderef",
109 r" 112 r"
110 struct A { the_field: (u32, i32) } 113 struct A { the_field: (u32, i32) }
111 impl A { 114 impl A {
@@ -114,27 +117,26 @@ mod tests {
114 } 117 }
115 } 118 }
116 ", 119 ",
117 r#"the_field "(u32, i32)"
118 foo "foo($0)""#,
119 ); 120 );
120 } 121 }
121 122
122 #[test] 123 #[test]
123 fn test_no_struct_field_completion_for_method_call() { 124 fn test_no_struct_field_completion_for_method_call() {
124 check_ref_completion( 125 check_ref_completion(
126 "no_struct_field_completion_for_method_call",
125 r" 127 r"
126 struct A { the_field: u32 } 128 struct A { the_field: u32 }
127 fn foo(a: A) { 129 fn foo(a: A) {
128 a.<|>() 130 a.<|>()
129 } 131 }
130 ", 132 ",
131 r#""#,
132 ); 133 );
133 } 134 }
134 135
135 #[test] 136 #[test]
136 fn test_method_completion() { 137 fn test_method_completion() {
137 check_ref_completion( 138 check_ref_completion(
139 "method_completion",
138 r" 140 r"
139 struct A {} 141 struct A {}
140 impl A { 142 impl A {
@@ -144,13 +146,13 @@ mod tests {
144 a.<|> 146 a.<|>
145 } 147 }
146 ", 148 ",
147 r#"the_method "the_method($0)""#,
148 ); 149 );
149 } 150 }
150 151
151 #[test] 152 #[test]
152 fn test_no_non_self_method() { 153 fn test_no_non_self_method() {
153 check_ref_completion( 154 check_ref_completion(
155 "no_non_self_method",
154 r" 156 r"
155 struct A {} 157 struct A {}
156 impl A { 158 impl A {
@@ -160,7 +162,6 @@ mod tests {
160 a.<|> 162 a.<|>
161 } 163 }
162 ", 164 ",
163 r#""#,
164 ); 165 );
165 } 166 }
166} 167}
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs
index c1739e47e..e3d1470c2 100644
--- a/crates/ra_ide_api/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs
@@ -34,7 +34,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
34 } 34 }
35 }) 35 })
36 .for_each(|(label, lookup)| { 36 .for_each(|(label, lookup)| {
37 CompletionItem::new(CompletionKind::Magic, label) 37 CompletionItem::new(CompletionKind::Magic, ctx, label)
38 .lookup_by(lookup) 38 .lookup_by(lookup)
39 .add_to(acc) 39 .add_to(acc)
40 }); 40 });
@@ -56,38 +56,40 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
56#[cfg(test)] 56#[cfg(test)]
57mod tests { 57mod tests {
58 use crate::completion::*; 58 use crate::completion::*;
59 use crate::completion::completion_item::check_completion;
59 60
60 fn check_magic_completion(code: &str, expected_completions: &str) { 61 fn check_magic_completion(name: &str, code: &str) {
61 check_completion(code, expected_completions, CompletionKind::Magic); 62 check_completion(name, code, CompletionKind::Magic);
62 } 63 }
63 64
64 #[test] 65 #[test]
65 fn test_param_completion_last_param() { 66 fn test_param_completion_last_param() {
66 check_magic_completion( 67 check_magic_completion(
68 "param_completion_last_param",
67 r" 69 r"
68 fn foo(file_id: FileId) {} 70 fn foo(file_id: FileId) {}
69 fn bar(file_id: FileId) {} 71 fn bar(file_id: FileId) {}
70 fn baz(file<|>) {} 72 fn baz(file<|>) {}
71 ", 73 ",
72 r#"file_id "file_id: FileId""#,
73 ); 74 );
74 } 75 }
75 76
76 #[test] 77 #[test]
77 fn test_param_completion_nth_param() { 78 fn test_param_completion_nth_param() {
78 check_magic_completion( 79 check_magic_completion(
80 "param_completion_nth_param",
79 r" 81 r"
80 fn foo(file_id: FileId) {} 82 fn foo(file_id: FileId) {}
81 fn bar(file_id: FileId) {} 83 fn bar(file_id: FileId) {}
82 fn baz(file<|>, x: i32) {} 84 fn baz(file<|>, x: i32) {}
83 ", 85 ",
84 r#"file_id "file_id: FileId""#,
85 ); 86 );
86 } 87 }
87 88
88 #[test] 89 #[test]
89 fn test_param_completion_trait_param() { 90 fn test_param_completion_trait_param() {
90 check_magic_completion( 91 check_magic_completion(
92 "param_completion_trait_param",
91 r" 93 r"
92 pub(crate) trait SourceRoot { 94 pub(crate) trait SourceRoot {
93 pub fn contains(&self, file_id: FileId) -> bool; 95 pub fn contains(&self, file_id: FileId) -> bool;
@@ -96,7 +98,6 @@ mod tests {
96 pub fn syntax(&self, file<|>) 98 pub fn syntax(&self, file<|>)
97 } 99 }
98 ", 100 ",
99 r#"file_id "file_id: FileId""#,
100 ); 101 );
101 } 102 }
102} 103}
diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide_api/src/completion/complete_keyword.rs
index d350f06ce..3fbf36313 100644
--- a/crates/ra_ide_api/src/completion/complete_keyword.rs
+++ b/crates/ra_ide_api/src/completion/complete_keyword.rs
@@ -11,36 +11,33 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
11 // complete keyword "crate" in use stmt 11 // complete keyword "crate" in use stmt
12 match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) { 12 match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) {
13 (Some(_), None) => { 13 (Some(_), None) => {
14 CompletionItem::new(CompletionKind::Keyword, "crate") 14 CompletionItem::new(CompletionKind::Keyword, ctx, "crate")
15 .kind(CompletionItemKind::Keyword) 15 .kind(CompletionItemKind::Keyword)
16 .lookup_by("crate") 16 .insert_text("crate::")
17 .snippet("crate::")
18 .add_to(acc); 17 .add_to(acc);
19 CompletionItem::new(CompletionKind::Keyword, "self") 18 CompletionItem::new(CompletionKind::Keyword, ctx, "self")
20 .kind(CompletionItemKind::Keyword) 19 .kind(CompletionItemKind::Keyword)
21 .lookup_by("self")
22 .add_to(acc); 20 .add_to(acc);
23 CompletionItem::new(CompletionKind::Keyword, "super") 21 CompletionItem::new(CompletionKind::Keyword, ctx, "super")
24 .kind(CompletionItemKind::Keyword) 22 .kind(CompletionItemKind::Keyword)
25 .lookup_by("super") 23 .insert_text("super::")
26 .add_to(acc); 24 .add_to(acc);
27 } 25 }
28 (Some(_), Some(_)) => { 26 (Some(_), Some(_)) => {
29 CompletionItem::new(CompletionKind::Keyword, "self") 27 CompletionItem::new(CompletionKind::Keyword, ctx, "self")
30 .kind(CompletionItemKind::Keyword) 28 .kind(CompletionItemKind::Keyword)
31 .lookup_by("self")
32 .add_to(acc); 29 .add_to(acc);
33 CompletionItem::new(CompletionKind::Keyword, "super") 30 CompletionItem::new(CompletionKind::Keyword, ctx, "super")
34 .kind(CompletionItemKind::Keyword) 31 .kind(CompletionItemKind::Keyword)
35 .lookup_by("super") 32 .insert_text("super::")
36 .add_to(acc); 33 .add_to(acc);
37 } 34 }
38 _ => {} 35 _ => {}
39 } 36 }
40} 37}
41 38
42fn keyword(kw: &str, snippet: &str) -> CompletionItem { 39fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem {
43 CompletionItem::new(CompletionKind::Keyword, kw) 40 CompletionItem::new(CompletionKind::Keyword, ctx, kw)
44 .kind(CompletionItemKind::Keyword) 41 .kind(CompletionItemKind::Keyword)
45 .snippet(snippet) 42 .snippet(snippet)
46 .build() 43 .build()
@@ -55,25 +52,25 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
55 Some(it) => it, 52 Some(it) => it,
56 None => return, 53 None => return,
57 }; 54 };
58 acc.add(keyword("if", "if $0 {}")); 55 acc.add(keyword(ctx, "if", "if $0 {}"));
59 acc.add(keyword("match", "match $0 {}")); 56 acc.add(keyword(ctx, "match", "match $0 {}"));
60 acc.add(keyword("while", "while $0 {}")); 57 acc.add(keyword(ctx, "while", "while $0 {}"));
61 acc.add(keyword("loop", "loop {$0}")); 58 acc.add(keyword(ctx, "loop", "loop {$0}"));
62 59
63 if ctx.after_if { 60 if ctx.after_if {
64 acc.add(keyword("else", "else {$0}")); 61 acc.add(keyword(ctx, "else", "else {$0}"));
65 acc.add(keyword("else if", "else if $0 {}")); 62 acc.add(keyword(ctx, "else if", "else if $0 {}"));
66 } 63 }
67 if is_in_loop_body(ctx.leaf) { 64 if is_in_loop_body(ctx.leaf) {
68 if ctx.can_be_stmt { 65 if ctx.can_be_stmt {
69 acc.add(keyword("continue", "continue;")); 66 acc.add(keyword(ctx, "continue", "continue;"));
70 acc.add(keyword("break", "break;")); 67 acc.add(keyword(ctx, "break", "break;"));
71 } else { 68 } else {
72 acc.add(keyword("continue", "continue")); 69 acc.add(keyword(ctx, "continue", "continue"));
73 acc.add(keyword("break", "break")); 70 acc.add(keyword(ctx, "break", "break"));
74 } 71 }
75 } 72 }
76 acc.add_all(complete_return(fn_def, ctx.can_be_stmt)); 73 acc.add_all(complete_return(ctx, fn_def, ctx.can_be_stmt));
77} 74}
78 75
79fn is_in_loop_body(leaf: &SyntaxNode) -> bool { 76fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
@@ -95,78 +92,69 @@ fn is_in_loop_body(leaf: &SyntaxNode) -> bool {
95 false 92 false
96} 93}
97 94
98fn complete_return(fn_def: &ast::FnDef, can_be_stmt: bool) -> Option<CompletionItem> { 95fn complete_return(
96 ctx: &CompletionContext,
97 fn_def: &ast::FnDef,
98 can_be_stmt: bool,
99) -> Option<CompletionItem> {
99 let snip = match (can_be_stmt, fn_def.ret_type().is_some()) { 100 let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
100 (true, true) => "return $0;", 101 (true, true) => "return $0;",
101 (true, false) => "return;", 102 (true, false) => "return;",
102 (false, true) => "return $0", 103 (false, true) => "return $0",
103 (false, false) => "return", 104 (false, false) => "return",
104 }; 105 };
105 Some(keyword("return", snip)) 106 Some(keyword(ctx, "return", snip))
106} 107}
107 108
108#[cfg(test)] 109#[cfg(test)]
109mod tests { 110mod tests {
110 use crate::completion::{CompletionKind, check_completion}; 111 use crate::completion::CompletionKind;
111 fn check_keyword_completion(code: &str, expected_completions: &str) { 112 use crate::completion::completion_item::check_completion;
112 check_completion(code, expected_completions, CompletionKind::Keyword); 113
114 fn check_keyword_completion(name: &str, code: &str) {
115 check_completion(name, code, CompletionKind::Keyword);
113 } 116 }
114 117
115 #[test] 118 #[test]
116 fn completes_keywords_in_use_stmt() { 119 fn completes_keywords_in_use_stmt() {
117 check_keyword_completion( 120 check_keyword_completion(
121 "keywords_in_use_stmt1",
118 r" 122 r"
119 use <|> 123 use <|>
120 ", 124 ",
121 r#"
122 crate "crate" "crate::"
123 self "self"
124 super "super"
125 "#,
126 ); 125 );
127 126
128 check_keyword_completion( 127 check_keyword_completion(
128 "keywords_in_use_stmt2",
129 r" 129 r"
130 use a::<|> 130 use a::<|>
131 ", 131 ",
132 r#"
133 self "self"
134 super "super"
135 "#,
136 ); 132 );
137 133
138 check_keyword_completion( 134 check_keyword_completion(
135 "keywords_in_use_stmt3",
139 r" 136 r"
140 use a::{b, <|>} 137 use a::{b, <|>}
141 ", 138 ",
142 r#"
143 self "self"
144 super "super"
145 "#,
146 ); 139 );
147 } 140 }
148 141
149 #[test] 142 #[test]
150 fn completes_various_keywords_in_function() { 143 fn completes_various_keywords_in_function() {
151 check_keyword_completion( 144 check_keyword_completion(
145 "keywords_in_function1",
152 r" 146 r"
153 fn quux() { 147 fn quux() {
154 <|> 148 <|>
155 } 149 }
156 ", 150 ",
157 r#"
158 if "if $0 {}"
159 match "match $0 {}"
160 while "while $0 {}"
161 loop "loop {$0}"
162 return "return;"
163 "#,
164 ); 151 );
165 } 152 }
166 153
167 #[test] 154 #[test]
168 fn completes_else_after_if() { 155 fn completes_else_after_if() {
169 check_keyword_completion( 156 check_keyword_completion(
157 "keywords_in_function2",
170 r" 158 r"
171 fn quux() { 159 fn quux() {
172 if true { 160 if true {
@@ -174,55 +162,35 @@ mod tests {
174 } <|> 162 } <|>
175 } 163 }
176 ", 164 ",
177 r#"
178 if "if $0 {}"
179 match "match $0 {}"
180 while "while $0 {}"
181 loop "loop {$0}"
182 else "else {$0}"
183 else if "else if $0 {}"
184 return "return;"
185 "#,
186 ); 165 );
187 } 166 }
188 167
189 #[test] 168 #[test]
190 fn test_completion_return_value() { 169 fn test_completion_return_value() {
191 check_keyword_completion( 170 check_keyword_completion(
171 "keywords_in_function3",
192 r" 172 r"
193 fn quux() -> i32 { 173 fn quux() -> i32 {
194 <|> 174 <|>
195 92 175 92
196 } 176 }
197 ", 177 ",
198 r#"
199 if "if $0 {}"
200 match "match $0 {}"
201 while "while $0 {}"
202 loop "loop {$0}"
203 return "return $0;"
204 "#,
205 ); 178 );
206 check_keyword_completion( 179 check_keyword_completion(
180 "keywords_in_function4",
207 r" 181 r"
208 fn quux() { 182 fn quux() {
209 <|> 183 <|>
210 92 184 92
211 } 185 }
212 ", 186 ",
213 r#"
214 if "if $0 {}"
215 match "match $0 {}"
216 while "while $0 {}"
217 loop "loop {$0}"
218 return "return;"
219 "#,
220 ); 187 );
221 } 188 }
222 189
223 #[test] 190 #[test]
224 fn dont_add_semi_after_return_if_not_a_statement() { 191 fn dont_add_semi_after_return_if_not_a_statement() {
225 check_keyword_completion( 192 check_keyword_completion(
193 "dont_add_semi_after_return_if_not_a_statement",
226 r" 194 r"
227 fn quux() -> i32 { 195 fn quux() -> i32 {
228 match () { 196 match () {
@@ -230,19 +198,13 @@ mod tests {
230 } 198 }
231 } 199 }
232 ", 200 ",
233 r#"
234 if "if $0 {}"
235 match "match $0 {}"
236 while "while $0 {}"
237 loop "loop {$0}"
238 return "return $0"
239 "#,
240 ); 201 );
241 } 202 }
242 203
243 #[test] 204 #[test]
244 fn last_return_in_block_has_semi() { 205 fn last_return_in_block_has_semi() {
245 check_keyword_completion( 206 check_keyword_completion(
207 "last_return_in_block_has_semi1",
246 r" 208 r"
247 fn quux() -> i32 { 209 fn quux() -> i32 {
248 if condition { 210 if condition {
@@ -250,15 +212,9 @@ mod tests {
250 } 212 }
251 } 213 }
252 ", 214 ",
253 r#"
254 if "if $0 {}"
255 match "match $0 {}"
256 while "while $0 {}"
257 loop "loop {$0}"
258 return "return $0;"
259 "#,
260 ); 215 );
261 check_keyword_completion( 216 check_keyword_completion(
217 "last_return_in_block_has_semi2",
262 r" 218 r"
263 fn quux() -> i32 { 219 fn quux() -> i32 {
264 if condition { 220 if condition {
@@ -268,54 +224,35 @@ mod tests {
268 x 224 x
269 } 225 }
270 ", 226 ",
271 r#"
272 if "if $0 {}"
273 match "match $0 {}"
274 while "while $0 {}"
275 loop "loop {$0}"
276 return "return $0;"
277 "#,
278 ); 227 );
279 } 228 }
280 229
281 #[test] 230 #[test]
282 fn completes_break_and_continue_in_loops() { 231 fn completes_break_and_continue_in_loops() {
283 check_keyword_completion( 232 check_keyword_completion(
233 "completes_break_and_continue_in_loops1",
284 r" 234 r"
285 fn quux() -> i32 { 235 fn quux() -> i32 {
286 loop { <|> } 236 loop { <|> }
287 } 237 }
288 ", 238 ",
289 r#"
290 if "if $0 {}"
291 match "match $0 {}"
292 while "while $0 {}"
293 loop "loop {$0}"
294 continue "continue;"
295 break "break;"
296 return "return $0;"
297 "#,
298 ); 239 );
240
299 // No completion: lambda isolates control flow 241 // No completion: lambda isolates control flow
300 check_keyword_completion( 242 check_keyword_completion(
243 "completes_break_and_continue_in_loops2",
301 r" 244 r"
302 fn quux() -> i32 { 245 fn quux() -> i32 {
303 loop { || { <|> } } 246 loop { || { <|> } }
304 } 247 }
305 ", 248 ",
306 r#"
307 if "if $0 {}"
308 match "match $0 {}"
309 while "while $0 {}"
310 loop "loop {$0}"
311 return "return $0;"
312 "#,
313 ); 249 );
314 } 250 }
315 251
316 #[test] 252 #[test]
317 fn no_semi_after_break_continue_in_expr() { 253 fn no_semi_after_break_continue_in_expr() {
318 check_keyword_completion( 254 check_keyword_completion(
255 "no_semi_after_break_continue_in_expr",
319 r" 256 r"
320 fn f() { 257 fn f() {
321 loop { 258 loop {
@@ -325,15 +262,6 @@ mod tests {
325 } 262 }
326 } 263 }
327 ", 264 ",
328 r#"
329 if "if $0 {}"
330 match "match $0 {}"
331 while "while $0 {}"
332 loop "loop {$0}"
333 continue "continue"
334 break "break"
335 return "return"
336 "#,
337 ) 265 )
338 } 266 }
339} 267}
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 1eded7658..7413c71e8 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -15,7 +15,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
15 hir::Def::Module(module) => { 15 hir::Def::Module(module) => {
16 let module_scope = module.scope(ctx.db); 16 let module_scope = module.scope(ctx.db);
17 for (name, res) in module_scope.entries() { 17 for (name, res) in module_scope.entries() {
18 CompletionItem::new(CompletionKind::Reference, name.to_string()) 18 CompletionItem::new(CompletionKind::Reference, ctx, name.to_string())
19 .from_resolution(ctx, res) 19 .from_resolution(ctx, res)
20 .add_to(acc); 20 .add_to(acc);
21 } 21 }
@@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
24 e.variants(ctx.db) 24 e.variants(ctx.db)
25 .into_iter() 25 .into_iter()
26 .for_each(|(variant_name, _variant)| { 26 .for_each(|(variant_name, _variant)| {
27 CompletionItem::new(CompletionKind::Reference, variant_name.to_string()) 27 CompletionItem::new(CompletionKind::Reference, ctx, variant_name.to_string())
28 .kind(CompletionItemKind::EnumVariant) 28 .kind(CompletionItemKind::EnumVariant)
29 .add_to(acc) 29 .add_to(acc)
30 }); 30 });
@@ -35,7 +35,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
35 35
36#[cfg(test)] 36#[cfg(test)]
37mod tests { 37mod tests {
38 use crate::completion::{CompletionKind, check_completion}; 38 use crate::completion::CompletionKind;
39 use crate::completion::completion_item::check_completion;
39 40
40 fn check_reference_completion(code: &str, expected_completions: &str) { 41 fn check_reference_completion(code: &str, expected_completions: &str) {
41 check_completion(code, expected_completions, CompletionKind::Reference); 42 check_completion(code, expected_completions, CompletionKind::Reference);
@@ -44,6 +45,7 @@ mod tests {
44 #[test] 45 #[test]
45 fn completes_use_item_starting_with_self() { 46 fn completes_use_item_starting_with_self() {
46 check_reference_completion( 47 check_reference_completion(
48 "use_item_starting_with_self",
47 r" 49 r"
48 use self::m::<|>; 50 use self::m::<|>;
49 51
@@ -51,13 +53,13 @@ mod tests {
51 struct Bar; 53 struct Bar;
52 } 54 }
53 ", 55 ",
54 "Bar",
55 ); 56 );
56 } 57 }
57 58
58 #[test] 59 #[test]
59 fn completes_use_item_starting_with_crate() { 60 fn completes_use_item_starting_with_crate() {
60 check_reference_completion( 61 check_reference_completion(
62 "use_item_starting_with_crate",
61 " 63 "
62 //- /lib.rs 64 //- /lib.rs
63 mod foo; 65 mod foo;
@@ -65,13 +67,13 @@ mod tests {
65 //- /foo.rs 67 //- /foo.rs
66 use crate::Sp<|> 68 use crate::Sp<|>
67 ", 69 ",
68 "Spam;foo",
69 ); 70 );
70 } 71 }
71 72
72 #[test] 73 #[test]
73 fn completes_nested_use_tree() { 74 fn completes_nested_use_tree() {
74 check_reference_completion( 75 check_reference_completion(
76 "nested_use_tree",
75 " 77 "
76 //- /lib.rs 78 //- /lib.rs
77 mod foo; 79 mod foo;
@@ -79,13 +81,13 @@ mod tests {
79 //- /foo.rs 81 //- /foo.rs
80 use crate::{Sp<|>}; 82 use crate::{Sp<|>};
81 ", 83 ",
82 "Spam;foo",
83 ); 84 );
84 } 85 }
85 86
86 #[test] 87 #[test]
87 fn completes_deeply_nested_use_tree() { 88 fn completes_deeply_nested_use_tree() {
88 check_reference_completion( 89 check_reference_completion(
90 "deeply_nested_use_tree",
89 " 91 "
90 //- /lib.rs 92 //- /lib.rs
91 mod foo; 93 mod foo;
@@ -97,37 +99,37 @@ mod tests {
97 //- /foo.rs 99 //- /foo.rs
98 use crate::{bar::{baz::Sp<|>}}; 100 use crate::{bar::{baz::Sp<|>}};
99 ", 101 ",
100 "Spam",
101 ); 102 );
102 } 103 }
103 104
104 #[test] 105 #[test]
105 fn completes_enum_variant() { 106 fn completes_enum_variant() {
106 check_reference_completion( 107 check_reference_completion(
108 "reference_completion",
107 " 109 "
108 //- /lib.rs 110 //- /lib.rs
109 enum E { Foo, Bar(i32) } 111 enum E { Foo, Bar(i32) }
110 fn foo() { let _ = E::<|> } 112 fn foo() { let _ = E::<|> }
111 ", 113 ",
112 "Foo;Bar",
113 ); 114 );
114 } 115 }
115 116
116 #[test] 117 #[test]
117 fn dont_render_function_parens_in_use_item() { 118 fn dont_render_function_parens_in_use_item() {
118 check_reference_completion( 119 check_reference_completion(
120 "dont_render_function_parens_in_use_item",
119 " 121 "
120 //- /lib.rs 122 //- /lib.rs
121 mod m { pub fn foo() {} } 123 mod m { pub fn foo() {} }
122 use crate::m::f<|>; 124 use crate::m::f<|>;
123 ", 125 ",
124 "foo",
125 ) 126 )
126 } 127 }
127 128
128 #[test] 129 #[test]
129 fn dont_render_function_parens_if_already_call() { 130 fn dont_render_function_parens_if_already_call() {
130 check_reference_completion( 131 check_reference_completion(
132 "dont_render_function_parens_if_already_call",
131 " 133 "
132 //- /lib.rs 134 //- /lib.rs
133 fn frobnicate() {} 135 fn frobnicate() {}
@@ -135,7 +137,6 @@ mod tests {
135 frob<|>(); 137 frob<|>();
136 } 138 }
137 ", 139 ",
138 "main;frobnicate",
139 ) 140 )
140 } 141 }
141} 142}
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 4276e47e8..bb080a341 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -1,6 +1,5 @@
1use rustc_hash::FxHashSet; 1use rustc_hash::FxHashSet;
2use ra_syntax::{AstNode, TextUnit}; 2use ra_syntax::ast::AstNode;
3
4use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; 3use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
5 4
6pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
@@ -13,7 +12,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
13 }; 12 };
14 if let Some(function) = &ctx.function { 13 if let Some(function) = &ctx.function {
15 let scopes = function.scopes(ctx.db); 14 let scopes = function.scopes(ctx.db);
16 complete_fn(acc, &scopes, ctx.offset); 15 complete_fn(acc, &scopes, ctx);
17 } 16 }
18 17
19 let module_scope = module.scope(ctx.db); 18 let module_scope = module.scope(ctx.db);
@@ -30,20 +29,24 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
30 } 29 }
31 }) 30 })
32 .for_each(|(name, res)| { 31 .for_each(|(name, res)| {
33 CompletionItem::new(CompletionKind::Reference, name.to_string()) 32 CompletionItem::new(CompletionKind::Reference, ctx, name.to_string())
34 .from_resolution(ctx, res) 33 .from_resolution(ctx, res)
35 .add_to(acc) 34 .add_to(acc)
36 }); 35 });
37} 36}
38 37
39fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) { 38fn complete_fn(
39 acc: &mut Completions,
40 scopes: &hir::ScopesWithSyntaxMapping,
41 ctx: &CompletionContext,
42) {
40 let mut shadowed = FxHashSet::default(); 43 let mut shadowed = FxHashSet::default();
41 scopes 44 scopes
42 .scope_chain_for_offset(offset) 45 .scope_chain_for_offset(ctx.offset)
43 .flat_map(|scope| scopes.scopes.entries(scope).iter()) 46 .flat_map(|scope| scopes.scopes.entries(scope).iter())
44 .filter(|entry| shadowed.insert(entry.name())) 47 .filter(|entry| shadowed.insert(entry.name()))
45 .for_each(|entry| { 48 .for_each(|entry| {
46 CompletionItem::new(CompletionKind::Reference, entry.name().to_string()) 49 CompletionItem::new(CompletionKind::Reference, ctx, entry.name().to_string())
47 .kind(CompletionItemKind::Binding) 50 .kind(CompletionItemKind::Binding)
48 .add_to(acc) 51 .add_to(acc)
49 }); 52 });
@@ -51,15 +54,17 @@ fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, off
51 54
52#[cfg(test)] 55#[cfg(test)]
53mod tests { 56mod tests {
54 use crate::completion::{CompletionKind, check_completion}; 57 use crate::completion::CompletionKind;
58 use crate::completion::completion_item::check_completion;
55 59
56 fn check_reference_completion(code: &str, expected_completions: &str) { 60 fn check_reference_completion(name: &str, code: &str) {
57 check_completion(code, expected_completions, CompletionKind::Reference); 61 check_completion(name, code, CompletionKind::Reference);
58 } 62 }
59 63
60 #[test] 64 #[test]
61 fn completes_bindings_from_let() { 65 fn completes_bindings_from_let() {
62 check_reference_completion( 66 check_reference_completion(
67 "bindings_from_let",
63 r" 68 r"
64 fn quux(x: i32) { 69 fn quux(x: i32) {
65 let y = 92; 70 let y = 92;
@@ -67,13 +72,13 @@ mod tests {
67 let z = (); 72 let z = ();
68 } 73 }
69 ", 74 ",
70 r#"y;x;quux "quux($0)""#,
71 ); 75 );
72 } 76 }
73 77
74 #[test] 78 #[test]
75 fn completes_bindings_from_if_let() { 79 fn completes_bindings_from_if_let() {
76 check_reference_completion( 80 check_reference_completion(
81 "bindings_from_if_let",
77 r" 82 r"
78 fn quux() { 83 fn quux() {
79 if let Some(x) = foo() { 84 if let Some(x) = foo() {
@@ -85,13 +90,13 @@ mod tests {
85 } 90 }
86 } 91 }
87 ", 92 ",
88 r#"b;a;quux "quux()$0""#,
89 ); 93 );
90 } 94 }
91 95
92 #[test] 96 #[test]
93 fn completes_bindings_from_for() { 97 fn completes_bindings_from_for() {
94 check_reference_completion( 98 check_reference_completion(
99 "bindings_from_for",
95 r" 100 r"
96 fn quux() { 101 fn quux() {
97 for x in &[1, 2, 3] { 102 for x in &[1, 2, 3] {
@@ -99,13 +104,13 @@ mod tests {
99 } 104 }
100 } 105 }
101 ", 106 ",
102 r#"x;quux "quux()$0""#,
103 ); 107 );
104 } 108 }
105 109
106 #[test] 110 #[test]
107 fn completes_module_items() { 111 fn completes_module_items() {
108 check_reference_completion( 112 check_reference_completion(
113 "module_items",
109 r" 114 r"
110 struct Foo; 115 struct Foo;
111 enum Baz {} 116 enum Baz {}
@@ -113,13 +118,13 @@ mod tests {
113 <|> 118 <|>
114 } 119 }
115 ", 120 ",
116 r#"quux "quux()$0";Foo;Baz"#,
117 ); 121 );
118 } 122 }
119 123
120 #[test] 124 #[test]
121 fn completes_module_items_in_nested_modules() { 125 fn completes_module_items_in_nested_modules() {
122 check_reference_completion( 126 check_reference_completion(
127 "module_items_in_nested_modules",
123 r" 128 r"
124 struct Foo; 129 struct Foo;
125 mod m { 130 mod m {
@@ -127,24 +132,24 @@ mod tests {
127 fn quux() { <|> } 132 fn quux() { <|> }
128 } 133 }
129 ", 134 ",
130 r#"quux "quux()$0";Bar"#,
131 ); 135 );
132 } 136 }
133 137
134 #[test] 138 #[test]
135 fn completes_return_type() { 139 fn completes_return_type() {
136 check_reference_completion( 140 check_reference_completion(
141 "return_type",
137 r" 142 r"
138 struct Foo; 143 struct Foo;
139 fn x() -> <|> 144 fn x() -> <|>
140 ", 145 ",
141 r#"Foo;x "x()$0""#,
142 ) 146 )
143 } 147 }
144 148
145 #[test] 149 #[test]
146 fn dont_show_both_completions_for_shadowing() { 150 fn dont_show_both_completions_for_shadowing() {
147 check_reference_completion( 151 check_reference_completion(
152 "dont_show_both_completions_for_shadowing",
148 r" 153 r"
149 fn foo() -> { 154 fn foo() -> {
150 let bar = 92; 155 let bar = 92;
@@ -154,32 +159,29 @@ mod tests {
154 } 159 }
155 } 160 }
156 ", 161 ",
157 r#"bar;foo "foo()$0""#,
158 ) 162 )
159 } 163 }
160 164
161 #[test] 165 #[test]
162 fn completes_self_in_methods() { 166 fn completes_self_in_methods() {
163 check_reference_completion(r"impl S { fn foo(&self) { <|> } }", "self") 167 check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }")
164 } 168 }
165 169
166 #[test] 170 #[test]
167 fn inserts_parens_for_function_calls() { 171 fn inserts_parens_for_function_calls() {
168 check_reference_completion( 172 check_reference_completion(
173 "inserts_parens_for_function_calls1",
169 r" 174 r"
170 fn no_args() {} 175 fn no_args() {}
171 fn main() { no_<|> } 176 fn main() { no_<|> }
172 ", 177 ",
173 r#"no_args "no_args()$0"
174 main "main()$0""#,
175 ); 178 );
176 check_reference_completion( 179 check_reference_completion(
180 "inserts_parens_for_function_calls2",
177 r" 181 r"
178 fn with_args(x: i32, y: String) {} 182 fn with_args(x: i32, y: String) {}
179 fn main() { with_<|> } 183 fn main() { with_<|> }
180 ", 184 ",
181 r#"main "main()$0"
182 with_args "with_args($0)""#,
183 ); 185 );
184 } 186 }
185} 187}
diff --git a/crates/ra_ide_api/src/completion/complete_snippet.rs b/crates/ra_ide_api/src/completion/complete_snippet.rs
index a495751dd..fb94e3674 100644
--- a/crates/ra_ide_api/src/completion/complete_snippet.rs
+++ b/crates/ra_ide_api/src/completion/complete_snippet.rs
@@ -1,7 +1,7 @@
1use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionItemKind, CompletionContext, completion_item::Builder}; 1use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionItemKind, CompletionContext, completion_item::Builder};
2 2
3fn snippet(label: &str, snippet: &str) -> Builder { 3fn snippet<'a>(ctx: &'a CompletionContext<'a>, label: &str, snippet: &str) -> Builder<'a> {
4 CompletionItem::new(CompletionKind::Snippet, label) 4 CompletionItem::new(CompletionKind::Snippet, ctx, label)
5 .snippet(snippet) 5 .snippet(snippet)
6 .kind(CompletionItemKind::Snippet) 6 .kind(CompletionItemKind::Snippet)
7} 7}
@@ -10,8 +10,8 @@ pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
10 if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) { 10 if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
11 return; 11 return;
12 } 12 }
13 snippet("pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc); 13 snippet(ctx, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
14 snippet("ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc); 14 snippet(ctx, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
15} 15}
16 16
17pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { 17pub(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
19 return; 19 return;
20 } 20 }
21 snippet( 21 snippet(
22 ctx,
22 "Test function", 23 "Test function",
23 "\ 24 "\
24#[test] 25#[test]
@@ -29,45 +30,33 @@ fn ${1:feature}() {
29 .lookup_by("tfn") 30 .lookup_by("tfn")
30 .add_to(acc); 31 .add_to(acc);
31 32
32 snippet("pub(crate)", "pub(crate) $0").add_to(acc); 33 snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc);
33} 34}
34 35
35#[cfg(test)] 36#[cfg(test)]
36mod tests { 37mod tests {
37 use crate::completion::{CompletionKind, check_completion}; 38 use crate::completion::CompletionKind;
38 fn check_snippet_completion(code: &str, expected_completions: &str) { 39 use crate::completion::completion_item::check_completion;
39 check_completion(code, expected_completions, CompletionKind::Snippet); 40
41 fn check_snippet_completion(name: &str, code: &str) {
42 check_completion(name, code, CompletionKind::Snippet);
40 } 43 }
41 44
42 #[test] 45 #[test]
43 fn completes_snippets_in_expressions() { 46 fn completes_snippets_in_expressions() {
44 check_snippet_completion( 47 check_snippet_completion("snippets_in_expressions", r"fn foo(x: i32) { <|> }");
45 r"fn foo(x: i32) { <|> }",
46 r##"
47 pd "eprintln!(\"$0 = {:?}\", $0);"
48 ppd "eprintln!(\"$0 = {:#?}\", $0);"
49 "##,
50 );
51 } 48 }
52 49
53 #[test] 50 #[test]
54 fn completes_snippets_in_items() { 51 fn completes_snippets_in_items() {
55 // check_snippet_completion(r"
56 // <|>
57 // ",
58 // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
59 // );
60 check_snippet_completion( 52 check_snippet_completion(
53 "snippets_in_items",
61 r" 54 r"
62 #[cfg(test)] 55 #[cfg(test)]
63 mod tests { 56 mod tests {
64 <|> 57 <|>
65 } 58 }
66 ", 59 ",
67 r##"
68 tfn "Test function" "#[test]\nfn ${1:feature}() {\n $0\n}"
69 pub(crate) "pub(crate) $0"
70 "##,
71 ); 60 );
72 } 61 }
73} 62}
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index e537e0082..de9b95c81 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -12,7 +12,7 @@ use crate::{db, FilePosition};
12/// `CompletionContext` is created early during completion to figure out, where 12/// `CompletionContext` is created early during completion to figure out, where
13/// exactly is the cursor, syntax-wise. 13/// exactly is the cursor, syntax-wise.
14#[derive(Debug)] 14#[derive(Debug)]
15pub(super) struct CompletionContext<'a> { 15pub(crate) struct CompletionContext<'a> {
16 pub(super) db: &'a db::RootDatabase, 16 pub(super) db: &'a db::RootDatabase,
17 pub(super) offset: TextUnit, 17 pub(super) offset: TextUnit,
18 pub(super) leaf: &'a SyntaxNode, 18 pub(super) leaf: &'a SyntaxNode,
@@ -65,6 +65,10 @@ impl<'a> CompletionContext<'a> {
65 Some(ctx) 65 Some(ctx)
66 } 66 }
67 67
68 pub(crate) fn leaf_range(&self) -> TextRange {
69 self.leaf.range()
70 }
71
68 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) { 72 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
69 // Insert a fake ident to get a valid parse tree. We will use this file 73 // Insert a fake ident to get a valid parse tree. We will use this file
70 // to determine context, though the original_file will be used for 74 // to determine context, though the original_file will be used for
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 11d00f78c..7bd634498 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,6 +1,10 @@
1use hir::PerNs; 1use hir::PerNs;
2use ra_text_edit::{
3 AtomTextEdit,
4 TextEdit,
5};
2 6
3use crate::completion::CompletionContext; 7use crate::completion::completion_context::CompletionContext;
4 8
5/// `CompletionItem` describes a single completion variant in the editor pop-up. 9/// `CompletionItem` describes a single completion variant in the editor pop-up.
6/// It is basically a POD with various properties. To construct a 10/// It is basically a POD with various properties. To construct a
@@ -11,15 +15,29 @@ pub struct CompletionItem {
11 /// completion. 15 /// completion.
12 completion_kind: CompletionKind, 16 completion_kind: CompletionKind,
13 label: String, 17 label: String,
18 kind: Option<CompletionItemKind>,
14 detail: Option<String>, 19 detail: Option<String>,
15 lookup: Option<String>, 20 lookup: Option<String>,
16 snippet: Option<String>, 21 /// The format of the insert text. The format applies to both the `insert_text` property
17 kind: Option<CompletionItemKind>, 22 /// and the `insert` property of a provided `text_edit`.
18} 23 insert_text_format: InsertTextFormat,
19 24 /// An edit which is applied to a document when selecting this completion. When an edit is
20pub enum InsertText { 25 /// provided the value of `insert_text` is ignored.
21 PlainText { text: String }, 26 ///
22 Snippet { text: String }, 27 /// *Note:* The range of the edit must be a single line range and it must contain the position
28 /// at which completion has been requested.
29 ///
30 /// *Note:* If sending a range that overlaps a string, the string should match the relevant
31 /// part of the replacement text, or be filtered out.
32 text_edit: Option<AtomTextEdit>,
33 /// An optional array of additional text edits that are applied when
34 /// selecting this completion. Edits must not overlap (including the same insert position)
35 /// with the main edit nor with themselves.
36 ///
37 /// Additional text edits should be used to change text unrelated to the current cursor position
38 /// (for example adding an import statement at the top of the file if the completion item will
39 /// insert an unqualified type).
40 additional_text_edits: Option<TextEdit>,
23} 41}
24 42
25#[derive(Debug, Clone, Copy, PartialEq, Eq)] 43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -40,7 +58,7 @@ pub enum CompletionItemKind {
40 Method, 58 Method,
41} 59}
42 60
43#[derive(Debug, PartialEq, Eq)] 61#[derive(Debug, PartialEq, Eq, Copy, Clone)]
44pub(crate) enum CompletionKind { 62pub(crate) enum CompletionKind {
45 /// Parser-based keyword completion. 63 /// Parser-based keyword completion.
46 Keyword, 64 Keyword,
@@ -51,16 +69,30 @@ pub(crate) enum CompletionKind {
51 Snippet, 69 Snippet,
52} 70}
53 71
72#[derive(Debug, PartialEq, Eq, Copy, Clone)]
73pub enum InsertTextFormat {
74 PlainText,
75 Snippet,
76}
77
54impl CompletionItem { 78impl CompletionItem {
55 pub(crate) fn new(completion_kind: CompletionKind, label: impl Into<String>) -> Builder { 79 pub(crate) fn new<'a>(
80 completion_kind: CompletionKind,
81 ctx: &'a CompletionContext,
82 label: impl Into<String>,
83 ) -> Builder<'a> {
56 let label = label.into(); 84 let label = label.into();
57 Builder { 85 Builder {
86 ctx,
58 completion_kind, 87 completion_kind,
59 label, 88 label,
89 insert_text: None,
90 insert_text_format: InsertTextFormat::PlainText,
60 detail: None, 91 detail: None,
61 lookup: None, 92 lookup: None,
62 snippet: None,
63 kind: None, 93 kind: None,
94 text_edit: None,
95 additional_text_edits: None,
64 } 96 }
65 } 97 }
66 /// What user sees in pop-up in the UI. 98 /// What user sees in pop-up in the UI.
@@ -78,64 +110,100 @@ impl CompletionItem {
78 .map(|it| it.as_str()) 110 .map(|it| it.as_str())
79 .unwrap_or(self.label()) 111 .unwrap_or(self.label())
80 } 112 }
81 /// What is inserted. 113
82 pub fn insert_text(&self) -> InsertText { 114 pub fn insert_text_format(&self) -> InsertTextFormat {
83 match &self.snippet { 115 self.insert_text_format.clone()
84 None => InsertText::PlainText {
85 text: self.label.clone(),
86 },
87 Some(it) => InsertText::Snippet { text: it.clone() },
88 }
89 } 116 }
90 117
91 pub fn kind(&self) -> Option<CompletionItemKind> { 118 pub fn kind(&self) -> Option<CompletionItemKind> {
92 self.kind 119 self.kind
93 } 120 }
121 pub fn text_edit(&mut self) -> Option<&AtomTextEdit> {
122 self.text_edit.as_ref()
123 }
124 pub fn take_additional_text_edits(&mut self) -> Option<TextEdit> {
125 self.additional_text_edits.take()
126 }
94} 127}
95 128
96/// A helper to make `CompletionItem`s. 129/// A helper to make `CompletionItem`s.
97#[must_use] 130#[must_use]
98pub(crate) struct Builder { 131pub(crate) struct Builder<'a> {
132 ctx: &'a CompletionContext<'a>,
99 completion_kind: CompletionKind, 133 completion_kind: CompletionKind,
100 label: String, 134 label: String,
135 insert_text: Option<String>,
136 insert_text_format: InsertTextFormat,
101 detail: Option<String>, 137 detail: Option<String>,
102 lookup: Option<String>, 138 lookup: Option<String>,
103 snippet: Option<String>,
104 kind: Option<CompletionItemKind>, 139 kind: Option<CompletionItemKind>,
140 text_edit: Option<AtomTextEdit>,
141 additional_text_edits: Option<TextEdit>,
105} 142}
106 143
107impl Builder { 144impl<'a> Builder<'a> {
108 pub(crate) fn add_to(self, acc: &mut Completions) { 145 pub(crate) fn add_to(self, acc: &mut Completions) {
109 acc.add(self.build()) 146 acc.add(self.build())
110 } 147 }
111 148
112 pub(crate) fn build(self) -> CompletionItem { 149 pub(crate) fn build(self) -> CompletionItem {
150 let self_text_edit = self.text_edit;
151 let self_insert_text = self.insert_text;
152 let text_edit = match (self_text_edit, self_insert_text) {
153 (Some(text_edit), ..) => Some(text_edit),
154 (None, Some(insert_text)) => {
155 Some(AtomTextEdit::replace(self.ctx.leaf_range(), insert_text))
156 }
157 _ => None,
158 };
159
113 CompletionItem { 160 CompletionItem {
114 label: self.label, 161 label: self.label,
115 detail: self.detail, 162 detail: self.detail,
163 insert_text_format: self.insert_text_format,
116 lookup: self.lookup, 164 lookup: self.lookup,
117 snippet: self.snippet,
118 kind: self.kind, 165 kind: self.kind,
119 completion_kind: self.completion_kind, 166 completion_kind: self.completion_kind,
167 text_edit,
168 additional_text_edits: self.additional_text_edits,
120 } 169 }
121 } 170 }
122 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { 171 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder<'a> {
123 self.lookup = Some(lookup.into()); 172 self.lookup = Some(lookup.into());
124 self 173 self
125 } 174 }
126 pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder { 175 pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder<'a> {
127 self.snippet = Some(snippet.into()); 176 self.insert_text = Some(insert_text.into());
177 self
178 }
179 pub(crate) fn insert_text_format(
180 mut self,
181 insert_text_format: InsertTextFormat,
182 ) -> Builder<'a> {
183 self.insert_text_format = insert_text_format;
128 self 184 self
129 } 185 }
130 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder { 186 pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder<'a> {
187 self.insert_text_format = InsertTextFormat::Snippet;
188 self.insert_text(snippet)
189 }
190 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder<'a> {
131 self.kind = Some(kind); 191 self.kind = Some(kind);
132 self 192 self
133 } 193 }
194 pub(crate) fn text_edit(mut self, text_edit: AtomTextEdit) -> Builder<'a> {
195 self.text_edit = Some(text_edit);
196 self
197 }
198 pub(crate) fn additional_text_edits(mut self, additional_text_edits: TextEdit) -> Builder<'a> {
199 self.additional_text_edits = Some(additional_text_edits);
200 self
201 }
134 #[allow(unused)] 202 #[allow(unused)]
135 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { 203 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder<'a> {
136 self.set_detail(Some(detail)) 204 self.set_detail(Some(detail))
137 } 205 }
138 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { 206 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder<'a> {
139 self.detail = detail.map(Into::into); 207 self.detail = detail.map(Into::into);
140 self 208 self
141 } 209 }
@@ -143,7 +211,7 @@ impl Builder {
143 mut self, 211 mut self,
144 ctx: &CompletionContext, 212 ctx: &CompletionContext,
145 resolution: &hir::Resolution, 213 resolution: &hir::Resolution,
146 ) -> Builder { 214 ) -> Builder<'a> {
147 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); 215 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db));
148 let kind = match resolved { 216 let kind = match resolved {
149 PerNs { 217 PerNs {
@@ -188,21 +256,22 @@ impl Builder {
188 mut self, 256 mut self,
189 ctx: &CompletionContext, 257 ctx: &CompletionContext,
190 function: hir::Function, 258 function: hir::Function,
191 ) -> Builder { 259 ) -> Builder<'a> {
192 // If not an import, add parenthesis automatically. 260 // If not an import, add parenthesis automatically.
193 if ctx.use_item_syntax.is_none() && !ctx.is_call { 261 if ctx.use_item_syntax.is_none() && !ctx.is_call {
194 if function.signature(ctx.db).params().is_empty() { 262 if function.signature(ctx.db).params().is_empty() {
195 self.snippet = Some(format!("{}()$0", self.label)); 263 self.insert_text = Some(format!("{}()$0", self.label));
196 } else { 264 } else {
197 self.snippet = Some(format!("{}($0)", self.label)); 265 self.insert_text = Some(format!("{}($0)", self.label));
198 } 266 }
267 self.insert_text_format = InsertTextFormat::Snippet;
199 } 268 }
200 self.kind = Some(CompletionItemKind::Function); 269 self.kind = Some(CompletionItemKind::Function);
201 self 270 self
202 } 271 }
203} 272}
204 273
205impl Into<CompletionItem> for Builder { 274impl<'a> Into<CompletionItem> for Builder<'a> {
206 fn into(self) -> CompletionItem { 275 fn into(self) -> CompletionItem {
207 self.build() 276 self.build()
208 } 277 }
@@ -225,60 +294,6 @@ impl Completions {
225 { 294 {
226 items.into_iter().for_each(|item| self.add(item.into())) 295 items.into_iter().for_each(|item| self.add(item.into()))
227 } 296 }
228
229 #[cfg(test)]
230 pub(crate) fn assert_match(&self, expected: &str, kind: CompletionKind) {
231 let expected = normalize(expected);
232 let actual = self.debug_render(kind);
233 test_utils::assert_eq_text!(expected.as_str(), actual.as_str(),);
234
235 /// Normalize the textual representation of `Completions`:
236 /// replace `;` with newlines, normalize whitespace
237 fn normalize(expected: &str) -> String {
238 use ra_syntax::{tokenize, TextUnit, TextRange, SyntaxKind::SEMI};
239 let mut res = String::new();
240 for line in expected.trim().lines() {
241 let line = line.trim();
242 let mut start_offset: TextUnit = 0.into();
243 // Yep, we use rust tokenize in completion tests :-)
244 for token in tokenize(line) {
245 let range = TextRange::offset_len(start_offset, token.len);
246 start_offset += token.len;
247 if token.kind == SEMI {
248 res.push('\n');
249 } else {
250 res.push_str(&line[range]);
251 }
252 }
253
254 res.push('\n');
255 }
256 res
257 }
258 }
259
260 #[cfg(test)]
261 fn debug_render(&self, kind: CompletionKind) -> String {
262 let mut res = String::new();
263 for c in self.buf.iter() {
264 if c.completion_kind == kind {
265 if let Some(lookup) = &c.lookup {
266 res.push_str(lookup);
267 res.push_str(&format!(" {:?}", c.label));
268 } else {
269 res.push_str(&c.label);
270 }
271 if let Some(detail) = &c.detail {
272 res.push_str(&format!(" {:?}", detail));
273 }
274 if let Some(snippet) = &c.snippet {
275 res.push_str(&format!(" {:?}", snippet));
276 }
277 res.push('\n');
278 }
279 }
280 res
281 }
282} 297}
283 298
284impl Into<Vec<CompletionItem>> for Completions { 299impl Into<Vec<CompletionItem>> for Completions {
@@ -286,3 +301,22 @@ impl Into<Vec<CompletionItem>> for Completions {
286 self.buf 301 self.buf
287 } 302 }
288} 303}
304
305#[cfg(test)]
306pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind) {
307 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
308 use crate::completion::completions;
309 use insta::assert_debug_snapshot_matches;
310 let (analysis, position) = if code.contains("//-") {
311 analysis_and_position(code)
312 } else {
313 single_file_with_position(code)
314 };
315 let completions = completions(&analysis.db, position).unwrap();
316 let completion_items: Vec<CompletionItem> = completions.into();
317 let kind_completions: Vec<CompletionItem> = completion_items
318 .into_iter()
319 .filter(|c| c.completion_kind == kind)
320 .collect();
321 assert_debug_snapshot_matches!(test_name, kind_completions);
322}
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
index 000000000..40a5fd90f
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_for.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.835266+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "x",
9 kind: Some(
10 Binding
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "quux",
21 kind: Some(
22 Function
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: Snippet,
27 text_edit: Some(
28 AtomTextEdit {
29 delete: [62; 100),
30 insert: "quux()$0"
31 }
32 ),
33 additional_text_edits: None
34 }
35]
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
index 000000000..f6c0d7501
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_if_let.snap
@@ -0,0 +1,47 @@
1Created: 2019-01-19T13:42:17.835796+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "b",
9 kind: Some(
10 Binding
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "a",
21 kind: Some(
22 Binding
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 },
30 CompletionItem {
31 completion_kind: Reference,
32 label: "quux",
33 kind: Some(
34 Function
35 ),
36 detail: None,
37 lookup: None,
38 insert_text_format: Snippet,
39 text_edit: Some(
40 AtomTextEdit {
41 delete: [213; 231),
42 insert: "quux()$0"
43 }
44 ),
45 additional_text_edits: None
46 }
47]
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
index 000000000..a6fda0cf2
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__bindings_from_let.snap
@@ -0,0 +1,47 @@
1Created: 2019-01-19T13:42:17.835351+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "y",
9 kind: Some(
10 Binding
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "x",
21 kind: Some(
22 Binding
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 },
30 CompletionItem {
31 completion_kind: Reference,
32 label: "quux",
33 kind: Some(
34 Function
35 ),
36 detail: None,
37 lookup: None,
38 insert_text_format: Snippet,
39 text_edit: Some(
40 AtomTextEdit {
41 delete: [78; 79),
42 insert: "quux($0)"
43 }
44 ),
45 additional_text_edits: None
46 }
47]
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
index 000000000..b27674da4
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops1.snap
@@ -0,0 +1,125 @@
1Created: 2019-01-19T13:42:17.819543+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [54; 56),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [54; 56),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [54; 56),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [54; 56),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "continue",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [54; 56),
86 insert: "continue;"
87 }
88 ),
89 additional_text_edits: None
90 },
91 CompletionItem {
92 completion_kind: Keyword,
93 label: "break",
94 kind: Some(
95 Keyword
96 ),
97 detail: None,
98 lookup: None,
99 insert_text_format: Snippet,
100 text_edit: Some(
101 AtomTextEdit {
102 delete: [54; 56),
103 insert: "break;"
104 }
105 ),
106 additional_text_edits: None
107 },
108 CompletionItem {
109 completion_kind: Keyword,
110 label: "return",
111 kind: Some(
112 Keyword
113 ),
114 detail: None,
115 lookup: None,
116 insert_text_format: Snippet,
117 text_edit: Some(
118 AtomTextEdit {
119 delete: [54; 56),
120 insert: "return $0;"
121 }
122 ),
123 additional_text_edits: None
124 }
125]
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
index 000000000..4ebc16822
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_break_and_continue_in_loops2.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.830288+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [59; 61),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [59; 61),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [59; 61),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [59; 61),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [59; 61),
86 insert: "return $0;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..60b5a7424
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completion_postfix.snap
@@ -0,0 +1,102 @@
1Created: 2019-01-19T13:50:41.824939+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Postfix,
8 label: "not",
9 kind: None,
10 detail: None,
11 lookup: None,
12 insert_text_format: Snippet,
13 text_edit: Some(
14 AtomTextEdit {
15 delete: [78; 78),
16 insert: "!not"
17 }
18 ),
19 additional_text_edits: Some(
20 TextEdit {
21 atoms: [
22 AtomTextEdit {
23 delete: [72; 78),
24 insert: ""
25 }
26 ]
27 }
28 )
29 },
30 CompletionItem {
31 completion_kind: Postfix,
32 label: "if",
33 kind: None,
34 detail: None,
35 lookup: None,
36 insert_text_format: Snippet,
37 text_edit: Some(
38 AtomTextEdit {
39 delete: [78; 78),
40 insert: "if bar {$0}"
41 }
42 ),
43 additional_text_edits: Some(
44 TextEdit {
45 atoms: [
46 AtomTextEdit {
47 delete: [72; 78),
48 insert: ""
49 }
50 ]
51 }
52 )
53 },
54 CompletionItem {
55 completion_kind: Postfix,
56 label: "match",
57 kind: None,
58 detail: None,
59 lookup: None,
60 insert_text_format: Snippet,
61 text_edit: Some(
62 AtomTextEdit {
63 delete: [78; 78),
64 insert: "match bar {\n${1:_} => {$0\\},\n}"
65 }
66 ),
67 additional_text_edits: Some(
68 TextEdit {
69 atoms: [
70 AtomTextEdit {
71 delete: [72; 78),
72 insert: ""
73 }
74 ]
75 }
76 )
77 },
78 CompletionItem {
79 completion_kind: Postfix,
80 label: "while",
81 kind: None,
82 detail: None,
83 lookup: None,
84 insert_text_format: Snippet,
85 text_edit: Some(
86 AtomTextEdit {
87 delete: [78; 78),
88 insert: "while bar {\n$0\n}"
89 }
90 ),
91 additional_text_edits: Some(
92 TextEdit {
93 atoms: [
94 AtomTextEdit {
95 delete: [72; 78),
96 insert: ""
97 }
98 ]
99 }
100 )
101 }
102]
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
index 000000000..b33bc3e04
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__deeply_nested_use_tree.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:53:16.799862+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Spam",
9 kind: Some(
10 Struct
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..0a96291ab
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_add_semi_after_return_if_not_a_statement.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.821375+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [84; 102),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [84; 102),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [84; 102),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [84; 102),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [84; 102),
86 insert: "return $0"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..5126c2bdc
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_if_already_call.snap
@@ -0,0 +1,30 @@
1Created: 2019-01-19T11:53:16.799845+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "main",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "frobnicate",
21 kind: Some(
22 Function
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 }
30]
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
index 000000000..dd91e337a
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_render_function_parens_in_use_item.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:53:16.799820+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "foo",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..9c1c3fe6a
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__dont_show_both_completions_for_shadowing.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.841643+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "bar",
9 kind: Some(
10 Binding
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "foo",
21 kind: Some(
22 Function
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: Snippet,
27 text_edit: Some(
28 AtomTextEdit {
29 delete: [108; 146),
30 insert: "foo()$0"
31 }
32 ),
33 additional_text_edits: None
34 }
35]
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
index 000000000..7d693be77
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls1.snap
@@ -0,0 +1,40 @@
1Created: 2019-01-19T13:42:17.844671+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "no_args",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [53; 56),
18 insert: "no_args()$0"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Reference,
25 label: "main",
26 kind: Some(
27 Function
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [53; 56),
35 insert: "main()$0"
36 }
37 ),
38 additional_text_edits: None
39 }
40]
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
index 000000000..1d2946c49
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__inserts_parens_for_function_calls2.snap
@@ -0,0 +1,40 @@
1Created: 2019-01-19T13:42:17.849139+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "main",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [72; 77),
18 insert: "main()$0"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Reference,
25 label: "with_args",
26 kind: Some(
27 Function
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [72; 77),
35 insert: "with_args($0)"
36 }
37 ),
38 additional_text_edits: None
39 }
40]
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
index 000000000..2059d63e8
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function1.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.819926+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [24; 54),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [24; 54),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [24; 54),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [24; 54),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [24; 54),
86 insert: "return;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..2cc81582c
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function2.snap
@@ -0,0 +1,125 @@
1Created: 2019-01-19T13:42:17.819839+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [91; 105),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [91; 105),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [91; 105),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [91; 105),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "else",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [91; 105),
86 insert: "else {$0}"
87 }
88 ),
89 additional_text_edits: None
90 },
91 CompletionItem {
92 completion_kind: Keyword,
93 label: "else if",
94 kind: Some(
95 Keyword
96 ),
97 detail: None,
98 lookup: None,
99 insert_text_format: Snippet,
100 text_edit: Some(
101 AtomTextEdit {
102 delete: [91; 105),
103 insert: "else if $0 {}"
104 }
105 ),
106 additional_text_edits: None
107 },
108 CompletionItem {
109 completion_kind: Keyword,
110 label: "return",
111 kind: Some(
112 Keyword
113 ),
114 detail: None,
115 lookup: None,
116 insert_text_format: Snippet,
117 text_edit: Some(
118 AtomTextEdit {
119 delete: [91; 105),
120 insert: "return;"
121 }
122 ),
123 additional_text_edits: None
124 }
125]
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
index 000000000..26dec82c7
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function3.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.822255+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [31; 65),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [31; 65),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [31; 65),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [31; 65),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [31; 65),
86 insert: "return $0;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..4167165ec
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_function4.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.830680+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [24; 58),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [24; 58),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [24; 58),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [24; 58),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [24; 58),
86 insert: "return;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..db137d896
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt1.snap
@@ -0,0 +1,52 @@
1Created: 2019-01-19T13:42:17.819227+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "crate",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [16; 30),
18 insert: "crate::"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "self",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: PlainText,
32 text_edit: None,
33 additional_text_edits: None
34 },
35 CompletionItem {
36 completion_kind: Keyword,
37 label: "super",
38 kind: Some(
39 Keyword
40 ),
41 detail: None,
42 lookup: None,
43 insert_text_format: PlainText,
44 text_edit: Some(
45 AtomTextEdit {
46 delete: [16; 30),
47 insert: "super::"
48 }
49 ),
50 additional_text_edits: None
51 }
52]
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
index 000000000..1ff0f4939
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt2.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.822990+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "self",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Keyword,
20 label: "super",
21 kind: Some(
22 Keyword
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: Some(
28 AtomTextEdit {
29 delete: [18; 20),
30 insert: "super::"
31 }
32 ),
33 additional_text_edits: None
34 }
35]
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
index 000000000..e14bd209c
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__keywords_in_use_stmt3.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.826915+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "self",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Keyword,
20 label: "super",
21 kind: Some(
22 Keyword
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: Some(
28 AtomTextEdit {
29 delete: [23; 24),
30 insert: "super::"
31 }
32 ),
33 additional_text_edits: None
34 }
35]
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
index 000000000..a72828355
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi1.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.821139+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [62; 100),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [62; 100),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [62; 100),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [62; 100),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [62; 100),
86 insert: "return $0;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..c5d5e74cb
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__last_return_in_block_has_semi2.snap
@@ -0,0 +1,91 @@
1Created: 2019-01-19T13:42:17.829078+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [62; 100),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [62; 100),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [62; 100),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [62; 100),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "return",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [62; 100),
86 insert: "return $0;"
87 }
88 ),
89 additional_text_edits: None
90 }
91]
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
index 000000000..c18b44d59
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__method_completion.snap
@@ -0,0 +1,23 @@
1Created: 2019-01-19T13:42:17.817204+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "the_method",
9 kind: Some(
10 Method
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [143; 144),
18 insert: "the_method($0)"
19 }
20 ),
21 additional_text_edits: None
22 }
23]
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
index 000000000..8d262a91d
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items.snap
@@ -0,0 +1,47 @@
1Created: 2019-01-19T13:42:17.835687+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "quux",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [72; 102),
18 insert: "quux()$0"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Reference,
25 label: "Foo",
26 kind: Some(
27 Struct
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: PlainText,
32 text_edit: None,
33 additional_text_edits: None
34 },
35 CompletionItem {
36 completion_kind: Reference,
37 label: "Baz",
38 kind: Some(
39 Enum
40 ),
41 detail: None,
42 lookup: None,
43 insert_text_format: PlainText,
44 text_edit: None,
45 additional_text_edits: None
46 }
47]
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
index 000000000..097344521
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__module_items_in_nested_modules.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.836102+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "quux",
9 kind: Some(
10 Function
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [100; 102),
18 insert: "quux()$0"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Reference,
25 label: "Bar",
26 kind: Some(
27 Struct
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: PlainText,
32 text_edit: None,
33 additional_text_edits: None
34 }
35]
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
index 000000000..dbe1e0445
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__nested_use_tree.snap
@@ -0,0 +1,30 @@
1Created: 2019-01-19T11:53:16.799743+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Spam",
9 kind: Some(
10 Struct
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "foo",
21 kind: Some(
22 Module
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 }
30]
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
index 000000000..417b692dc
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_non_self_method.snap
@@ -0,0 +1,5 @@
1Created: 2019-01-19T11:34:11.702251+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[]
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
index 000000000..26c54018e
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_semi_after_break_continue_in_expr.snap
@@ -0,0 +1,125 @@
1Created: 2019-01-19T13:42:17.821881+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Keyword,
8 label: "if",
9 kind: Some(
10 Keyword
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [106; 108),
18 insert: "if $0 {}"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Keyword,
25 label: "match",
26 kind: Some(
27 Keyword
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [106; 108),
35 insert: "match $0 {}"
36 }
37 ),
38 additional_text_edits: None
39 },
40 CompletionItem {
41 completion_kind: Keyword,
42 label: "while",
43 kind: Some(
44 Keyword
45 ),
46 detail: None,
47 lookup: None,
48 insert_text_format: Snippet,
49 text_edit: Some(
50 AtomTextEdit {
51 delete: [106; 108),
52 insert: "while $0 {}"
53 }
54 ),
55 additional_text_edits: None
56 },
57 CompletionItem {
58 completion_kind: Keyword,
59 label: "loop",
60 kind: Some(
61 Keyword
62 ),
63 detail: None,
64 lookup: None,
65 insert_text_format: Snippet,
66 text_edit: Some(
67 AtomTextEdit {
68 delete: [106; 108),
69 insert: "loop {$0}"
70 }
71 ),
72 additional_text_edits: None
73 },
74 CompletionItem {
75 completion_kind: Keyword,
76 label: "continue",
77 kind: Some(
78 Keyword
79 ),
80 detail: None,
81 lookup: None,
82 insert_text_format: Snippet,
83 text_edit: Some(
84 AtomTextEdit {
85 delete: [106; 108),
86 insert: "continue"
87 }
88 ),
89 additional_text_edits: None
90 },
91 CompletionItem {
92 completion_kind: Keyword,
93 label: "break",
94 kind: Some(
95 Keyword
96 ),
97 detail: None,
98 lookup: None,
99 insert_text_format: Snippet,
100 text_edit: Some(
101 AtomTextEdit {
102 delete: [106; 108),
103 insert: "break"
104 }
105 ),
106 additional_text_edits: None
107 },
108 CompletionItem {
109 completion_kind: Keyword,
110 label: "return",
111 kind: Some(
112 Keyword
113 ),
114 detail: None,
115 lookup: None,
116 insert_text_format: Snippet,
117 text_edit: Some(
118 AtomTextEdit {
119 delete: [106; 108),
120 insert: "return"
121 }
122 ),
123 additional_text_edits: None
124 }
125]
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
index 000000000..0948c9fe6
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__no_struct_field_completion_for_method_call.snap
@@ -0,0 +1,5 @@
1Created: 2019-01-19T11:34:11.702201+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[]
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
index 000000000..160da9e31
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_last_param.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:27:14.070727+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Magic,
8 label: "file_id: FileId",
9 kind: None,
10 detail: None,
11 lookup: Some(
12 "file_id"
13 ),
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..baeb01ed9
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_nth_param.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:29:09.355053+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Magic,
8 label: "file_id: FileId",
9 kind: None,
10 detail: None,
11 lookup: Some(
12 "file_id"
13 ),
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..8193c4f17
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__param_completion_trait_param.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:29:09.355066+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Magic,
8 label: "file_id: FileId",
9 kind: None,
10 detail: None,
11 lookup: Some(
12 "file_id"
13 ),
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..abd17dcec
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap
@@ -0,0 +1,30 @@
1Created: 2019-01-19T11:53:16.799765+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Foo",
9 kind: Some(
10 EnumVariant
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "Bar",
21 kind: Some(
22 EnumVariant
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 }
30]
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
index 000000000..c00a5ea5d
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__return_type.snap
@@ -0,0 +1,35 @@
1Created: 2019-01-19T13:42:17.837692+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Foo",
9 kind: Some(
10 Struct
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "x",
21 kind: Some(
22 Function
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: Snippet,
27 text_edit: Some(
28 AtomTextEdit {
29 delete: [46; 60),
30 insert: "x()$0"
31 }
32 ),
33 additional_text_edits: None
34 }
35]
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
index 000000000..263b15156
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:59:18.394156+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "self",
9 kind: Some(
10 Binding
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
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
index 000000000..82f0a6d8d
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_expressions.snap
@@ -0,0 +1,40 @@
1Created: 2019-01-19T13:42:17.844708+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Snippet,
8 label: "pd",
9 kind: Some(
10 Snippet
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: Snippet,
15 text_edit: Some(
16 AtomTextEdit {
17 delete: [16; 18),
18 insert: "eprintln!(\"$0 = {:?}\", $0);"
19 }
20 ),
21 additional_text_edits: None
22 },
23 CompletionItem {
24 completion_kind: Snippet,
25 label: "ppd",
26 kind: Some(
27 Snippet
28 ),
29 detail: None,
30 lookup: None,
31 insert_text_format: Snippet,
32 text_edit: Some(
33 AtomTextEdit {
34 delete: [16; 18),
35 insert: "eprintln!(\"$0 = {:#?}\", $0);"
36 }
37 ),
38 additional_text_edits: None
39 }
40]
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
index 000000000..e7cc5c410
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__snippets_in_items.snap
@@ -0,0 +1,42 @@
1Created: 2019-01-19T13:42:17.845616+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Snippet,
8 label: "Test function",
9 kind: Some(
10 Snippet
11 ),
12 detail: None,
13 lookup: Some(
14 "tfn"
15 ),
16 insert_text_format: Snippet,
17 text_edit: Some(
18 AtomTextEdit {
19 delete: [49; 79),
20 insert: "#[test]\nfn ${1:feature}() {\n $0\n}"
21 }
22 ),
23 additional_text_edits: None
24 },
25 CompletionItem {
26 completion_kind: Snippet,
27 label: "pub(crate)",
28 kind: Some(
29 Snippet
30 ),
31 detail: None,
32 lookup: None,
33 insert_text_format: Snippet,
34 text_edit: Some(
35 AtomTextEdit {
36 delete: [49; 79),
37 insert: "pub(crate) $0"
38 }
39 ),
40 additional_text_edits: None
41 }
42]
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
index 000000000..d27ca5f8f
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion.snap
@@ -0,0 +1,20 @@
1Created: 2019-01-19T11:34:11.702218+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "the_field",
9 kind: Some(
10 Field
11 ),
12 detail: Some(
13 "u32"
14 ),
15 lookup: None,
16 insert_text_format: PlainText,
17 text_edit: None,
18 additional_text_edits: None
19 }
20]
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
index 000000000..8e547ad37
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_autoderef.snap
@@ -0,0 +1,37 @@
1Created: 2019-01-19T13:42:17.817216+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "the_field",
9 kind: Some(
10 Field
11 ),
12 detail: Some(
13 "(u32, i32)"
14 ),
15 lookup: None,
16 insert_text_format: PlainText,
17 text_edit: None,
18 additional_text_edits: None
19 },
20 CompletionItem {
21 completion_kind: Reference,
22 label: "foo",
23 kind: Some(
24 Method
25 ),
26 detail: None,
27 lookup: None,
28 insert_text_format: Snippet,
29 text_edit: Some(
30 AtomTextEdit {
31 delete: [125; 126),
32 insert: "foo($0)"
33 }
34 ),
35 additional_text_edits: None
36 }
37]
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
index 000000000..4536cee17
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_field_completion_self.snap
@@ -0,0 +1,37 @@
1Created: 2019-01-19T13:42:17.817207+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "the_field",
9 kind: Some(
10 Field
11 ),
12 detail: Some(
13 "(u32,)"
14 ),
15 lookup: None,
16 insert_text_format: PlainText,
17 text_edit: None,
18 additional_text_edits: None
19 },
20 CompletionItem {
21 completion_kind: Reference,
22 label: "foo",
23 kind: Some(
24 Method
25 ),
26 detail: None,
27 lookup: None,
28 insert_text_format: Snippet,
29 text_edit: Some(
30 AtomTextEdit {
31 delete: [120; 121),
32 insert: "foo($0)"
33 }
34 ),
35 additional_text_edits: None
36 }
37]
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
index 000000000..4c35be33a
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_crate.snap
@@ -0,0 +1,30 @@
1Created: 2019-01-19T11:53:16.799683+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Spam",
9 kind: Some(
10 Struct
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 },
18 CompletionItem {
19 completion_kind: Reference,
20 label: "foo",
21 kind: Some(
22 Module
23 ),
24 detail: None,
25 lookup: None,
26 insert_text_format: PlainText,
27 text_edit: None,
28 additional_text_edits: None
29 }
30]
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
index 000000000..9780d652a
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__use_item_starting_with_self.snap
@@ -0,0 +1,18 @@
1Created: 2019-01-19T11:53:16.799788+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/src/completion/completion_item.rs
4
5[
6 CompletionItem {
7 completion_kind: Reference,
8 label: "Bar",
9 kind: Some(
10 Struct
11 ),
12 detail: None,
13 lookup: None,
14 insert_text_format: PlainText,
15 text_edit: None,
16 additional_text_edits: None
17 }
18]
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 33bef178a..fb0821ff6 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -43,7 +43,7 @@ use crate::{
43}; 43};
44 44
45pub use crate::{ 45pub use crate::{
46 completion::{CompletionItem, CompletionItemKind, InsertText}, 46 completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
47 runnables::{Runnable, RunnableKind}, 47 runnables::{Runnable, RunnableKind},
48 navigation_target::NavigationTarget, 48 navigation_target::NavigationTarget,
49}; 49};
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 6e187d49e..76215a975 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -1,13 +1,13 @@
1use lsp_types::{ 1use lsp_types::{
2 self, CreateFile, DocumentChangeOperation, DocumentChanges, InsertTextFormat, Location, LocationLink, 2 self, CreateFile, DocumentChangeOperation, DocumentChanges, Location, LocationLink,
3 Position, Range, RenameFile, ResourceOp, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, 3 Position, Range, RenameFile, ResourceOp, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
4 TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, 4 TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
5 WorkspaceEdit, 5 WorkspaceEdit,
6}; 6};
7use ra_ide_api::{ 7use ra_ide_api::{
8 CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit, 8 CompletionItem, CompletionItemKind, FileId, FilePosition, FileRange, FileSystemEdit,
9 InsertText, NavigationTarget, SourceChange, SourceFileEdit, RangeInfo, 9 NavigationTarget, SourceChange, SourceFileEdit, RangeInfo,
10 LineCol, LineIndex, translate_offset_with_edit 10 LineCol, LineIndex, translate_offset_with_edit, InsertTextFormat
11}; 11};
12use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 12use ra_syntax::{SyntaxKind, TextRange, TextUnit};
13use ra_text_edit::{AtomTextEdit, TextEdit}; 13use ra_text_edit::{AtomTextEdit, TextEdit};
@@ -74,27 +74,30 @@ impl Conv for CompletionItemKind {
74 } 74 }
75} 75}
76 76
77impl Conv for CompletionItem { 77impl ConvWith for CompletionItem {
78 type Ctx = LineIndex;
78 type Output = ::lsp_types::CompletionItem; 79 type Output = ::lsp_types::CompletionItem;
79 80
80 fn conv(self) -> <Self as Conv>::Output { 81 fn conv_with(mut self, ctx: &LineIndex) -> ::lsp_types::CompletionItem {
81 let mut res = ::lsp_types::CompletionItem { 82 let text_edit = self.text_edit().map(|t| t.conv_with(ctx));
83 let additonal_text_edit = self
84 .take_additional_text_edits()
85 .map(|it| it.conv_with(ctx));
86
87 let mut res = lsp_types::CompletionItem {
82 label: self.label().to_string(), 88 label: self.label().to_string(),
83 detail: self.detail().map(|it| it.to_string()), 89 detail: self.detail().map(|it| it.to_string()),
84 filter_text: Some(self.lookup().to_string()), 90 filter_text: Some(self.lookup().to_string()),
85 kind: self.kind().map(|it| it.conv()), 91 kind: self.kind().map(|it| it.conv()),
92 text_edit,
93 additional_text_edits: additonal_text_edit,
86 ..Default::default() 94 ..Default::default()
87 }; 95 };
88 match self.insert_text() { 96 res.insert_text_format = Some(match self.insert_text_format() {
89 InsertText::PlainText { text } => { 97 InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
90 res.insert_text = Some(text); 98 InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
91 res.insert_text_format = Some(InsertTextFormat::PlainText); 99 });
92 } 100
93 InsertText::Snippet { text } => {
94 res.insert_text = Some(text);
95 res.insert_text_format = Some(InsertTextFormat::Snippet);
96 }
97 }
98 res 101 res
99 } 102 }
100} 103}
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 8f9db68a2..d1e8c5774 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -337,7 +337,11 @@ pub fn handle_completion(
337 None => return Ok(None), 337 None => return Ok(None),
338 Some(items) => items, 338 Some(items) => items,
339 }; 339 };
340 let items = items.into_iter().map(|item| item.conv()).collect(); 340 let line_index = world.analysis().file_line_index(position.file_id);
341 let items = items
342 .into_iter()
343 .map(|item| item.conv_with(&line_index))
344 .collect();
341 345
342 Ok(Some(req::CompletionResponse::Array(items))) 346 Ok(Some(req::CompletionResponse::Array(items)))
343} 347}