aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-12 08:41:16 +0000
committerGitHub <[email protected]>2021-03-12 08:41:16 +0000
commitc01ef6eabab1fa70d3fdfed9c565fadec9f0a5ed (patch)
tree37160de8384855fd5fadce3ca4a3de4dacdf98b8 /crates/ide_completion/src
parentdb6364fecc2b0e9a95d9aaece820a86265b4cb4f (diff)
parent99c4a41cd1a9f9ef0ee4f067f0069a23123b949a (diff)
Merge #7974
7974: use references in CompletionItem's builder r=matklad a=yonip23 @matklad This is a follow up to [this pr](https://github.com/rust-analyzer/rust-analyzer/pull/7973) Co-authored-by: yonip23 <[email protected]>
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r--crates/ide_completion/src/completions/attribute.rs35
-rw-r--r--crates/ide_completion/src/completions/fn_param.rs7
-rw-r--r--crates/ide_completion/src/completions/keyword.rs44
-rw-r--r--crates/ide_completion/src/completions/mod_.rs7
-rw-r--r--crates/ide_completion/src/completions/postfix.rs1
-rw-r--r--crates/ide_completion/src/completions/record.rs15
-rw-r--r--crates/ide_completion/src/completions/snippet.rs25
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs31
-rw-r--r--crates/ide_completion/src/item.rs34
-rw-r--r--crates/ide_completion/src/render.rs62
-rw-r--r--crates/ide_completion/src/render/builder_ext.rs6
-rw-r--r--crates/ide_completion/src/render/const_.rs10
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs18
-rw-r--r--crates/ide_completion/src/render/function.rs12
-rw-r--r--crates/ide_completion/src/render/macro_.rs23
-rw-r--r--crates/ide_completion/src/render/pattern.rs9
-rw-r--r--crates/ide_completion/src/render/type_alias.rs10
17 files changed, 183 insertions, 166 deletions
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index cb05e85fc..14376b924 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -45,15 +45,15 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr
45 CompletionKind::Attribute, 45 CompletionKind::Attribute,
46 ctx.source_range(), 46 ctx.source_range(),
47 attr_completion.label, 47 attr_completion.label,
48 ) 48 );
49 .kind(CompletionItemKind::Attribute); 49 item.kind(CompletionItemKind::Attribute);
50 50
51 if let Some(lookup) = attr_completion.lookup { 51 if let Some(lookup) = attr_completion.lookup {
52 item = item.lookup_by(lookup); 52 item.lookup_by(lookup);
53 } 53 }
54 54
55 if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) { 55 if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) {
56 item = item.insert_snippet(cap, snippet); 56 item.insert_snippet(cap, snippet);
57 } 57 }
58 58
59 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { 59 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner {
@@ -168,16 +168,20 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input:
168 ); 168 );
169 let lookup = components.join(", "); 169 let lookup = components.join(", ");
170 let label = components.iter().rev().join(", "); 170 let label = components.iter().rev().join(", ");
171 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) 171 let mut builder =
172 .lookup_by(lookup) 172 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
173 .kind(CompletionItemKind::Attribute) 173 builder.lookup_by(lookup).kind(CompletionItemKind::Attribute);
174 .add_to(acc) 174 builder.add_to(acc);
175 } 175 }
176 176
177 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { 177 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
178 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), custom_derive_name) 178 let mut builder = CompletionItem::new(
179 .kind(CompletionItemKind::Attribute) 179 CompletionKind::Attribute,
180 .add_to(acc) 180 ctx.source_range(),
181 custom_derive_name,
182 );
183 builder.kind(CompletionItemKind::Attribute);
184 builder.add_to(acc);
181 } 185 }
182 } 186 }
183} 187}
@@ -193,14 +197,13 @@ fn complete_lint(
193 .into_iter() 197 .into_iter()
194 .filter(|completion| !existing_lints.contains(completion.label)) 198 .filter(|completion| !existing_lints.contains(completion.label))
195 { 199 {
196 CompletionItem::new( 200 let mut builder = CompletionItem::new(
197 CompletionKind::Attribute, 201 CompletionKind::Attribute,
198 ctx.source_range(), 202 ctx.source_range(),
199 lint_completion.label, 203 lint_completion.label,
200 ) 204 );
201 .kind(CompletionItemKind::Attribute) 205 builder.kind(CompletionItemKind::Attribute).detail(lint_completion.description);
202 .detail(lint_completion.description) 206 builder.add_to(acc)
203 .add_to(acc)
204 } 207 }
205 } 208 }
206} 209}
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs
index 1bcc8727f..9600a049a 100644
--- a/crates/ide_completion/src/completions/fn_param.rs
+++ b/crates/ide_completion/src/completions/fn_param.rs
@@ -54,10 +54,9 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
54 } 54 }
55 55
56 params.into_iter().for_each(|(label, lookup)| { 56 params.into_iter().for_each(|(label, lookup)| {
57 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) 57 let mut builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
58 .kind(CompletionItemKind::Binding) 58 builder.kind(CompletionItemKind::Binding).lookup_by(lookup);
59 .lookup_by(lookup) 59 builder.add_to(acc)
60 .add_to(acc)
61 }); 60 });
62} 61}
63 62
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 80aa9fb06..aa3be712d 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -12,21 +12,21 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
12 12
13 if ctx.use_item_syntax.is_some() { 13 if ctx.use_item_syntax.is_some() {
14 if ctx.path_qual.is_none() { 14 if ctx.path_qual.is_none() {
15 CompletionItem::new(CompletionKind::Keyword, source_range, "crate::") 15 let mut crate_builder =
16 .kind(CompletionItemKind::Keyword) 16 CompletionItem::new(CompletionKind::Keyword, source_range, "crate::");
17 .insert_text("crate::") 17 crate_builder.kind(CompletionItemKind::Keyword).insert_text("crate::");
18 .add_to(acc); 18 crate_builder.add_to(acc);
19 } 19 }
20 CompletionItem::new(CompletionKind::Keyword, source_range, "self") 20 let mut self_builder = CompletionItem::new(CompletionKind::Keyword, source_range, "self");
21 .kind(CompletionItemKind::Keyword) 21 self_builder.kind(CompletionItemKind::Keyword);
22 .add_to(acc); 22 self_builder.add_to(acc);
23 if iter::successors(ctx.path_qual.clone(), |p| p.qualifier()) 23 if iter::successors(ctx.path_qual.clone(), |p| p.qualifier())
24 .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) 24 .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
25 { 25 {
26 CompletionItem::new(CompletionKind::Keyword, source_range, "super::") 26 let mut super_builder =
27 .kind(CompletionItemKind::Keyword) 27 CompletionItem::new(CompletionKind::Keyword, source_range, "super::");
28 .insert_text("super::") 28 super_builder.kind(CompletionItemKind::Keyword).insert_text("super::");
29 .add_to(acc); 29 super_builder.add_to(acc);
30 } 30 }
31 } 31 }
32 32
@@ -34,11 +34,10 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
34 if let Some(receiver) = &ctx.dot_receiver { 34 if let Some(receiver) = &ctx.dot_receiver {
35 if let Some(ty) = ctx.sema.type_of_expr(receiver) { 35 if let Some(ty) = ctx.sema.type_of_expr(receiver) {
36 if ty.impls_future(ctx.db) { 36 if ty.impls_future(ctx.db) {
37 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 37 let mut builder =
38 .kind(CompletionItemKind::Keyword) 38 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
39 .detail("expr.await") 39 builder.kind(CompletionItemKind::Keyword).detail("expr.await").insert_text("await");
40 .insert_text("await") 40 builder.add_to(acc);
41 .add_to(acc);
42 } 41 }
43 }; 42 };
44 } 43 }
@@ -165,9 +164,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
165} 164}
166 165
167fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { 166fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
168 let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) 167 let mut builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw);
169 .kind(CompletionItemKind::Keyword); 168 builder.kind(CompletionItemKind::Keyword);
170 let builder = match ctx.config.snippet_cap { 169
170 match ctx.config.snippet_cap {
171 Some(cap) => { 171 Some(cap) => {
172 let tmp; 172 let tmp;
173 let snippet = if snippet.ends_with('}') && ctx.incomplete_let { 173 let snippet = if snippet.ends_with('}') && ctx.incomplete_let {
@@ -177,9 +177,11 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet
177 } else { 177 } else {
178 snippet 178 snippet
179 }; 179 };
180 builder.insert_snippet(cap, snippet) 180 builder.insert_snippet(cap, snippet);
181 }
182 None => {
183 builder.insert_text(if snippet.contains('$') { kw } else { snippet });
181 } 184 }
182 None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }),
183 }; 185 };
184 acc.add(builder.build()); 186 acc.add(builder.build());
185} 187}
diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs
index 352fc7c77..fc4ac7a0d 100644
--- a/crates/ide_completion/src/completions/mod_.rs
+++ b/crates/ide_completion/src/completions/mod_.rs
@@ -80,9 +80,10 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
80 if mod_under_caret.semicolon_token().is_none() { 80 if mod_under_caret.semicolon_token().is_none() {
81 label.push(';'); 81 label.push(';');
82 } 82 }
83 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) 83 let mut builder =
84 .kind(SymbolKind::Module) 84 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label);
85 .add_to(acc) 85 builder.kind(SymbolKind::Module);
86 builder.add_to(acc)
86 }); 87 });
87 88
88 Some(()) 89 Some(())
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs
index d45ad7944..8551e0168 100644
--- a/crates/ide_completion/src/completions/postfix.rs
+++ b/crates/ide_completion/src/completions/postfix.rs
@@ -301,6 +301,7 @@ fn postfix_snippet(
301 .detail(detail) 301 .detail(detail)
302 .kind(CompletionItemKind::Snippet) 302 .kind(CompletionItemKind::Snippet)
303 .snippet_edit(cap, edit) 303 .snippet_edit(cap, edit)
304 .clone()
304} 305}
305 306
306#[cfg(test)] 307#[cfg(test)]
diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs
index 0a7927eb8..b9af09698 100644
--- a/crates/ide_completion/src/completions/record.rs
+++ b/crates/ide_completion/src/completions/record.rs
@@ -22,16 +22,13 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
22 let completion_text = completion_text 22 let completion_text = completion_text
23 .strip_prefix(ctx.token.to_string().as_str()) 23 .strip_prefix(ctx.token.to_string().as_str())
24 .unwrap_or(completion_text); 24 .unwrap_or(completion_text);
25 acc.add( 25 let mut builder = CompletionItem::new(
26 CompletionItem::new( 26 CompletionKind::Snippet,
27 CompletionKind::Snippet, 27 ctx.source_range(),
28 ctx.source_range(), 28 "..Default::default()",
29 "..Default::default()",
30 )
31 .insert_text(completion_text)
32 .kind(SymbolKind::Field)
33 .build(),
34 ); 29 );
30 builder.insert_text(completion_text).kind(SymbolKind::Field);
31 acc.add(builder.build());
35 } 32 }
36 33
37 missing_fields 34 missing_fields
diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs
index df17a15c5..a4d18cecd 100644
--- a/crates/ide_completion/src/completions/snippet.rs
+++ b/crates/ide_completion/src/completions/snippet.rs
@@ -8,9 +8,8 @@ use crate::{
8}; 8};
9 9
10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { 10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
11 CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label) 11 let mut builder = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label);
12 .insert_snippet(cap, snippet) 12 builder.insert_snippet(cap, snippet).kind(CompletionItemKind::Snippet).clone()
13 .kind(CompletionItemKind::Snippet)
14} 13}
15 14
16pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) { 15pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
@@ -35,7 +34,7 @@ pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
35 None => return, 34 None => return,
36 }; 35 };
37 36
38 snippet( 37 let mut test_module_builder = snippet(
39 ctx, 38 ctx,
40 cap, 39 cap,
41 "tmod (Test module)", 40 "tmod (Test module)",
@@ -49,11 +48,11 @@ mod tests {
49 $0 48 $0
50 } 49 }
51}", 50}",
52 ) 51 );
53 .lookup_by("tmod") 52 test_module_builder.lookup_by("tmod");
54 .add_to(acc); 53 test_module_builder.add_to(acc);
55 54
56 snippet( 55 let mut test_function_builder = snippet(
57 ctx, 56 ctx,
58 cap, 57 cap,
59 "tfn (Test function)", 58 "tfn (Test function)",
@@ -62,11 +61,13 @@ mod tests {
62fn ${1:feature}() { 61fn ${1:feature}() {
63 $0 62 $0
64}", 63}",
65 ) 64 );
66 .lookup_by("tfn") 65 test_function_builder.lookup_by("tfn");
67 .add_to(acc); 66 test_function_builder.add_to(acc);
68 67
69 snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc); 68 let macro_rules_builder =
69 snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}");
70 macro_rules_builder.add_to(acc);
70} 71}
71 72
72#[cfg(test)] 73#[cfg(test)]
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index b999540b8..031f42d4a 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -145,9 +145,8 @@ fn add_function_impl(
145 format!("fn {}(..)", fn_name) 145 format!("fn {}(..)", fn_name)
146 }; 146 };
147 147
148 let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label) 148 let mut builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
149 .lookup_by(fn_name) 149 builder.lookup_by(fn_name).set_documentation(func.docs(ctx.db));
150 .set_documentation(func.docs(ctx.db));
151 150
152 let completion_kind = if func.self_param(ctx.db).is_some() { 151 let completion_kind = if func.self_param(ctx.db).is_some() {
153 CompletionItemKind::Method 152 CompletionItemKind::Method
@@ -161,15 +160,15 @@ fn add_function_impl(
161 match ctx.config.snippet_cap { 160 match ctx.config.snippet_cap {
162 Some(cap) => { 161 Some(cap) => {
163 let snippet = format!("{} {{\n $0\n}}", function_decl); 162 let snippet = format!("{} {{\n $0\n}}", function_decl);
164 builder.snippet_edit(cap, TextEdit::replace(range, snippet)) 163 builder.snippet_edit(cap, TextEdit::replace(range, snippet));
165 } 164 }
166 None => { 165 None => {
167 let header = format!("{} {{", function_decl); 166 let header = format!("{} {{", function_decl);
168 builder.text_edit(TextEdit::replace(range, header)) 167 builder.text_edit(TextEdit::replace(range, header));
169 } 168 }
170 } 169 };
171 .kind(completion_kind) 170 builder.kind(completion_kind);
172 .add_to(acc); 171 builder.add_to(acc);
173 } 172 }
174} 173}
175 174
@@ -185,12 +184,14 @@ fn add_type_alias_impl(
185 184
186 let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end()); 185 let range = TextRange::new(type_def_node.text_range().start(), ctx.source_range().end());
187 186
188 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 187 let mut builder =
188 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
189 builder
189 .text_edit(TextEdit::replace(range, snippet)) 190 .text_edit(TextEdit::replace(range, snippet))
190 .lookup_by(alias_name) 191 .lookup_by(alias_name)
191 .kind(SymbolKind::TypeAlias) 192 .kind(SymbolKind::TypeAlias)
192 .set_documentation(type_alias.docs(ctx.db)) 193 .set_documentation(type_alias.docs(ctx.db));
193 .add_to(acc); 194 builder.add_to(acc);
194} 195}
195 196
196fn add_const_impl( 197fn add_const_impl(
@@ -208,12 +209,14 @@ fn add_const_impl(
208 let range = 209 let range =
209 TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); 210 TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
210 211
211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 212 let mut builder =
213 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
214 builder
212 .text_edit(TextEdit::replace(range, snippet)) 215 .text_edit(TextEdit::replace(range, snippet))
213 .lookup_by(const_name) 216 .lookup_by(const_name)
214 .kind(SymbolKind::Const) 217 .kind(SymbolKind::Const)
215 .set_documentation(const_.docs(ctx.db)) 218 .set_documentation(const_.docs(ctx.db));
216 .add_to(acc); 219 builder.add_to(acc);
217 } 220 }
218 } 221 }
219} 222}
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 14afec603..cf1aaa131 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -401,42 +401,42 @@ impl Builder {
401 import_to_add: self.import_to_add, 401 import_to_add: self.import_to_add,
402 } 402 }
403 } 403 }
404 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { 404 pub(crate) fn lookup_by(&mut self, lookup: impl Into<String>) -> &mut Builder {
405 self.lookup = Some(lookup.into()); 405 self.lookup = Some(lookup.into());
406 self 406 self
407 } 407 }
408 pub(crate) fn label(mut self, label: impl Into<String>) -> Builder { 408 pub(crate) fn label(&mut self, label: impl Into<String>) -> &mut Builder {
409 self.label = label.into(); 409 self.label = label.into();
410 self 410 self
411 } 411 }
412 pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder { 412 pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {
413 self.insert_text = Some(insert_text.into()); 413 self.insert_text = Some(insert_text.into());
414 self 414 self
415 } 415 }
416 pub(crate) fn insert_snippet( 416 pub(crate) fn insert_snippet(
417 mut self, 417 &mut self,
418 _cap: SnippetCap, 418 _cap: SnippetCap,
419 snippet: impl Into<String>, 419 snippet: impl Into<String>,
420 ) -> Builder { 420 ) -> &mut Builder {
421 self.insert_text_format = InsertTextFormat::Snippet; 421 self.insert_text_format = InsertTextFormat::Snippet;
422 self.insert_text(snippet) 422 self.insert_text(snippet)
423 } 423 }
424 pub(crate) fn kind(mut self, kind: impl Into<CompletionItemKind>) -> Builder { 424 pub(crate) fn kind(&mut self, kind: impl Into<CompletionItemKind>) -> &mut Builder {
425 self.kind = Some(kind.into()); 425 self.kind = Some(kind.into());
426 self 426 self
427 } 427 }
428 pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder { 428 pub(crate) fn text_edit(&mut self, edit: TextEdit) -> &mut Builder {
429 self.text_edit = Some(edit); 429 self.text_edit = Some(edit);
430 self 430 self
431 } 431 }
432 pub(crate) fn snippet_edit(mut self, _cap: SnippetCap, edit: TextEdit) -> Builder { 432 pub(crate) fn snippet_edit(&mut self, _cap: SnippetCap, edit: TextEdit) -> &mut Builder {
433 self.insert_text_format = InsertTextFormat::Snippet; 433 self.insert_text_format = InsertTextFormat::Snippet;
434 self.text_edit(edit) 434 self.text_edit(edit)
435 } 435 }
436 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { 436 pub(crate) fn detail(&mut self, detail: impl Into<String>) -> &mut Builder {
437 self.set_detail(Some(detail)) 437 self.set_detail(Some(detail))
438 } 438 }
439 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { 439 pub(crate) fn set_detail(&mut self, detail: Option<impl Into<String>>) -> &mut Builder {
440 self.detail = detail.map(Into::into); 440 self.detail = detail.map(Into::into);
441 if let Some(detail) = &self.detail { 441 if let Some(detail) = &self.detail {
442 if never!(detail.contains('\n'), "multiline detail:\n{}", detail) { 442 if never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
@@ -446,30 +446,30 @@ impl Builder {
446 self 446 self
447 } 447 }
448 #[allow(unused)] 448 #[allow(unused)]
449 pub(crate) fn documentation(self, docs: Documentation) -> Builder { 449 pub(crate) fn documentation(&mut self, docs: Documentation) -> &mut Builder {
450 self.set_documentation(Some(docs)) 450 self.set_documentation(Some(docs))
451 } 451 }
452 pub(crate) fn set_documentation(mut self, docs: Option<Documentation>) -> Builder { 452 pub(crate) fn set_documentation(&mut self, docs: Option<Documentation>) -> &mut Builder {
453 self.documentation = docs.map(Into::into); 453 self.documentation = docs.map(Into::into);
454 self 454 self
455 } 455 }
456 pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder { 456 pub(crate) fn set_deprecated(&mut self, deprecated: bool) -> &mut Builder {
457 self.deprecated = deprecated; 457 self.deprecated = deprecated;
458 self 458 self
459 } 459 }
460 pub(crate) fn set_relevance(mut self, relevance: Relevance) -> Builder { 460 pub(crate) fn set_relevance(&mut self, relevance: Relevance) -> &mut Builder {
461 self.relevance = relevance; 461 self.relevance = relevance;
462 self 462 self
463 } 463 }
464 pub(crate) fn trigger_call_info(mut self) -> Builder { 464 pub(crate) fn trigger_call_info(&mut self) -> &mut Builder {
465 self.trigger_call_info = Some(true); 465 self.trigger_call_info = Some(true);
466 self 466 self
467 } 467 }
468 pub(crate) fn add_import(mut self, import_to_add: Option<ImportEdit>) -> Builder { 468 pub(crate) fn add_import(&mut self, import_to_add: Option<ImportEdit>) -> &mut Builder {
469 self.import_to_add = import_to_add; 469 self.import_to_add = import_to_add;
470 self 470 self
471 } 471 }
472 pub(crate) fn ref_match(mut self, mutability: Mutability) -> Builder { 472 pub(crate) fn ref_match(&mut self, mutability: Mutability) -> &mut Builder {
473 self.ref_match = Some(mutability); 473 self.ref_match = Some(mutability);
474 self 474 self
475 } 475 }
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 8c8b149a1..c50cba0e0 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -145,28 +145,34 @@ impl<'a> Render<'a> {
145 fn add_field(&mut self, field: hir::Field, ty: &Type) -> CompletionItem { 145 fn add_field(&mut self, field: hir::Field, ty: &Type) -> CompletionItem {
146 let is_deprecated = self.ctx.is_deprecated(field); 146 let is_deprecated = self.ctx.is_deprecated(field);
147 let name = field.name(self.ctx.db()); 147 let name = field.name(self.ctx.db());
148 let mut item = CompletionItem::new( 148 let mut builder = CompletionItem::new(
149 CompletionKind::Reference, 149 CompletionKind::Reference,
150 self.ctx.source_range(), 150 self.ctx.source_range(),
151 name.to_string(), 151 name.to_string(),
152 ) 152 );
153 .kind(SymbolKind::Field) 153 builder
154 .detail(ty.display(self.ctx.db()).to_string()) 154 .kind(SymbolKind::Field)
155 .set_documentation(field.docs(self.ctx.db())) 155 .detail(ty.display(self.ctx.db()).to_string())
156 .set_deprecated(is_deprecated); 156 .set_documentation(field.docs(self.ctx.db()))
157 .set_deprecated(is_deprecated);
157 158
158 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &name.to_string()) { 159 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &name.to_string()) {
159 item = item.set_relevance(relevance); 160 builder.set_relevance(relevance);
160 } 161 }
161 162
162 item.build() 163 builder.build()
163 } 164 }
164 165
165 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { 166 fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem {
166 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string()) 167 let mut builder = CompletionItem::new(
167 .kind(SymbolKind::Field) 168 CompletionKind::Reference,
168 .detail(ty.display(self.ctx.db()).to_string()) 169 self.ctx.source_range(),
169 .build() 170 field.to_string(),
171 );
172
173 builder.kind(SymbolKind::Field).detail(ty.display(self.ctx.db()).to_string());
174
175 builder.build()
170 } 176 }
171 177
172 fn render_resolution( 178 fn render_resolution(
@@ -225,15 +231,13 @@ impl<'a> Render<'a> {
225 CompletionItemKind::SymbolKind(SymbolKind::SelfParam) 231 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
226 } 232 }
227 ScopeDef::Unknown => { 233 ScopeDef::Unknown => {
228 let item = CompletionItem::new( 234 let mut item = CompletionItem::new(
229 CompletionKind::Reference, 235 CompletionKind::Reference,
230 self.ctx.source_range(), 236 self.ctx.source_range(),
231 local_name, 237 local_name,
232 ) 238 );
233 .kind(CompletionItemKind::UnresolvedReference) 239 item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add);
234 .add_import(import_to_add) 240 return Some(item.build());
235 .build();
236 return Some(item);
237 } 241 }
238 }; 242 };
239 243
@@ -242,14 +246,14 @@ impl<'a> Render<'a> {
242 if let ScopeDef::Local(local) = resolution { 246 if let ScopeDef::Local(local) = resolution {
243 let ty = local.ty(self.ctx.db()); 247 let ty = local.ty(self.ctx.db());
244 if !ty.is_unknown() { 248 if !ty.is_unknown() {
245 item = item.detail(ty.display(self.ctx.db()).to_string()); 249 item.detail(ty.display(self.ctx.db()).to_string());
246 } 250 }
247 }; 251 };
248 252
249 if let ScopeDef::Local(local) = resolution { 253 if let ScopeDef::Local(local) = resolution {
250 let ty = local.ty(self.ctx.db()); 254 let ty = local.ty(self.ctx.db());
251 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) { 255 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) {
252 item = item.set_relevance(relevance) 256 item.set_relevance(relevance);
253 } 257 }
254 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() { 258 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() {
255 if let Some(ty_without_ref) = expected_type.remove_ref() { 259 if let Some(ty_without_ref) = expected_type.remove_ref() {
@@ -260,7 +264,7 @@ impl<'a> Render<'a> {
260 } else { 264 } else {
261 Mutability::Shared 265 Mutability::Shared
262 }; 266 };
263 item = item.ref_match(mutability) 267 item.ref_match(mutability);
264 } 268 }
265 } 269 }
266 } 270 }
@@ -281,21 +285,17 @@ impl<'a> Render<'a> {
281 }; 285 };
282 if has_non_default_type_params { 286 if has_non_default_type_params {
283 cov_mark::hit!(inserts_angle_brackets_for_generics); 287 cov_mark::hit!(inserts_angle_brackets_for_generics);
284 item = item 288 item.lookup_by(local_name.clone())
285 .lookup_by(local_name.clone())
286 .label(format!("{}<…>", local_name)) 289 .label(format!("{}<…>", local_name))
287 .insert_snippet(cap, format!("{}<$0>", local_name)); 290 .insert_snippet(cap, format!("{}<$0>", local_name));
288 } 291 }
289 } 292 }
290 } 293 }
291 294 item.kind(kind)
292 Some( 295 .add_import(import_to_add)
293 item.kind(kind) 296 .set_documentation(self.docs(resolution))
294 .add_import(import_to_add) 297 .set_deprecated(self.is_deprecated(resolution));
295 .set_documentation(self.docs(resolution)) 298 Some(item.build())
296 .set_deprecated(self.is_deprecated(resolution))
297 .build(),
298 )
299 } 299 }
300 300
301 fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> { 301 fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> {
diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs
index 95a7596c1..6d062b3b9 100644
--- a/crates/ide_completion/src/render/builder_ext.rs
+++ b/crates/ide_completion/src/render/builder_ext.rs
@@ -52,11 +52,11 @@ impl Builder {
52 } 52 }
53 53
54 pub(super) fn add_call_parens( 54 pub(super) fn add_call_parens(
55 mut self, 55 &mut self,
56 ctx: &CompletionContext, 56 ctx: &CompletionContext,
57 name: String, 57 name: String,
58 params: Params, 58 params: Params,
59 ) -> Builder { 59 ) -> &mut Builder {
60 if !self.should_add_parens(ctx) { 60 if !self.should_add_parens(ctx) {
61 return self; 61 return self;
62 } 62 }
@@ -71,7 +71,7 @@ impl Builder {
71 let (snippet, label) = if params.is_empty() { 71 let (snippet, label) = if params.is_empty() {
72 (format!("{}()$0", name), format!("{}()", name)) 72 (format!("{}()$0", name), format!("{}()", name))
73 } else { 73 } else {
74 self = self.trigger_call_info(); 74 self.trigger_call_info();
75 let snippet = match (ctx.config.add_call_argument_snippets, params) { 75 let snippet = match (ctx.config.add_call_argument_snippets, params) {
76 (true, Params::Named(params)) => { 76 (true, Params::Named(params)) => {
77 let function_params_snippet = 77 let function_params_snippet =
diff --git a/crates/ide_completion/src/render/const_.rs b/crates/ide_completion/src/render/const_.rs
index 5010b642a..8add369e4 100644
--- a/crates/ide_completion/src/render/const_.rs
+++ b/crates/ide_completion/src/render/const_.rs
@@ -36,17 +36,17 @@ impl<'a> ConstRender<'a> {
36 let name = self.name()?; 36 let name = self.name()?;
37 let detail = self.detail(); 37 let detail = self.detail();
38 38
39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let mut item =
40 .kind(SymbolKind::Const) 40 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name);
41 item.kind(SymbolKind::Const)
41 .set_documentation(self.ctx.docs(self.const_)) 42 .set_documentation(self.ctx.docs(self.const_))
42 .set_deprecated( 43 .set_deprecated(
43 self.ctx.is_deprecated(self.const_) 44 self.ctx.is_deprecated(self.const_)
44 || self.ctx.is_deprecated_assoc_item(self.const_), 45 || self.ctx.is_deprecated_assoc_item(self.const_),
45 ) 46 )
46 .detail(detail) 47 .detail(detail);
47 .build();
48 48
49 Some(item) 49 Some(item.build())
50 } 50 }
51 51
52 fn name(&self) -> Option<String> { 52 fn name(&self) -> Option<String> {
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index ed055c1fb..23c43496e 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -59,20 +59,20 @@ impl<'a> EnumRender<'a> {
59 CompletionKind::Reference, 59 CompletionKind::Reference,
60 self.ctx.source_range(), 60 self.ctx.source_range(),
61 self.qualified_name.clone(), 61 self.qualified_name.clone(),
62 ) 62 );
63 .kind(SymbolKind::Variant) 63 builder
64 .set_documentation(self.variant.docs(self.ctx.db())) 64 .kind(SymbolKind::Variant)
65 .set_deprecated(self.ctx.is_deprecated(self.variant)) 65 .set_documentation(self.variant.docs(self.ctx.db()))
66 .add_import(import_to_add) 66 .set_deprecated(self.ctx.is_deprecated(self.variant))
67 .detail(self.detail()); 67 .add_import(import_to_add)
68 .detail(self.detail());
68 69
69 if self.variant_kind == StructKind::Tuple { 70 if self.variant_kind == StructKind::Tuple {
70 cov_mark::hit!(inserts_parens_for_tuple_enums); 71 cov_mark::hit!(inserts_parens_for_tuple_enums);
71 let params = Params::Anonymous(self.variant.fields(self.ctx.db()).len()); 72 let params = Params::Anonymous(self.variant.fields(self.ctx.db()).len());
72 builder = 73 builder.add_call_parens(self.ctx.completion, self.short_qualified_name, params);
73 builder.add_call_parens(self.ctx.completion, self.short_qualified_name, params);
74 } else if self.path.is_some() { 74 } else if self.path.is_some() {
75 builder = builder.lookup_by(self.short_qualified_name); 75 builder.lookup_by(self.short_qualified_name);
76 } 76 }
77 77
78 builder.build() 78 builder.build()
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 5931945a8..1e2f45f14 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -41,7 +41,12 @@ impl<'a> FunctionRender<'a> {
41 41
42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { 42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
43 let params = self.params(); 43 let params = self.params();
44 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone()) 44 let mut builder = CompletionItem::new(
45 CompletionKind::Reference,
46 self.ctx.source_range(),
47 self.name.clone(),
48 );
49 builder
45 .kind(self.kind()) 50 .kind(self.kind())
46 .set_documentation(self.ctx.docs(self.func)) 51 .set_documentation(self.ctx.docs(self.func))
47 .set_deprecated( 52 .set_deprecated(
@@ -49,8 +54,9 @@ impl<'a> FunctionRender<'a> {
49 ) 54 )
50 .detail(self.detail()) 55 .detail(self.detail())
51 .add_call_parens(self.ctx.completion, self.name, params) 56 .add_call_parens(self.ctx.completion, self.name, params)
52 .add_import(import_to_add) 57 .add_import(import_to_add);
53 .build() 58
59 builder.build()
54 } 60 }
55 61
56 fn detail(&self) -> String { 62 fn detail(&self) -> String {
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index a6cf3e479..727f5e02e 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -40,24 +40,27 @@ impl<'a> MacroRender<'a> {
40 40
41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { 41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
42 let mut builder = 42 let mut builder =
43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) 43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label());
44 .kind(SymbolKind::Macro) 44 builder
45 .set_documentation(self.docs.clone()) 45 .kind(SymbolKind::Macro)
46 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 46 .set_documentation(self.docs.clone())
47 .add_import(import_to_add) 47 .set_deprecated(self.ctx.is_deprecated(self.macro_))
48 .set_detail(self.detail()); 48 .add_import(import_to_add)
49 .set_detail(self.detail());
49 50
50 let needs_bang = self.needs_bang(); 51 let needs_bang = self.needs_bang();
51 builder = match self.ctx.snippet_cap() { 52 match self.ctx.snippet_cap() {
52 Some(cap) if needs_bang => { 53 Some(cap) if needs_bang => {
53 let snippet = self.snippet(); 54 let snippet = self.snippet();
54 let lookup = self.lookup(); 55 let lookup = self.lookup();
55 builder.insert_snippet(cap, snippet).lookup_by(lookup) 56 builder.insert_snippet(cap, snippet).lookup_by(lookup);
57 }
58 None if needs_bang => {
59 builder.insert_text(self.banged_name());
56 } 60 }
57 None if needs_bang => builder.insert_text(self.banged_name()),
58 _ => { 61 _ => {
59 cov_mark::hit!(dont_insert_macro_call_parens_unncessary); 62 cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
60 builder.insert_text(&self.name) 63 builder.insert_text(&self.name);
61 } 64 }
62 }; 65 };
63 66
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index 465dfe00c..4d8f2b17d 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -71,15 +71,16 @@ fn build_completion(
71 pat: String, 71 pat: String,
72 item: impl HasAttrs + Copy, 72 item: impl HasAttrs + Copy,
73) -> CompletionItem { 73) -> CompletionItem {
74 let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) 74 let mut completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name);
75 completion
75 .kind(CompletionItemKind::Binding) 76 .kind(CompletionItemKind::Binding)
76 .set_documentation(ctx.docs(item)) 77 .set_documentation(ctx.docs(item))
77 .set_deprecated(ctx.is_deprecated(item)) 78 .set_deprecated(ctx.is_deprecated(item))
78 .detail(&pat); 79 .detail(&pat);
79 let completion = if let Some(snippet_cap) = ctx.snippet_cap() { 80 if let Some(snippet_cap) = ctx.snippet_cap() {
80 completion.insert_snippet(snippet_cap, pat) 81 completion.insert_snippet(snippet_cap, pat);
81 } else { 82 } else {
82 completion.insert_text(pat) 83 completion.insert_text(pat);
83 }; 84 };
84 completion.build() 85 completion.build()
85} 86}
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs
index bd97c3692..e47b4c745 100644
--- a/crates/ide_completion/src/render/type_alias.rs
+++ b/crates/ide_completion/src/render/type_alias.rs
@@ -36,17 +36,17 @@ impl<'a> TypeAliasRender<'a> {
36 let name = self.name()?; 36 let name = self.name()?;
37 let detail = self.detail(); 37 let detail = self.detail();
38 38
39 let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name) 39 let mut item =
40 .kind(SymbolKind::TypeAlias) 40 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name);
41 item.kind(SymbolKind::TypeAlias)
41 .set_documentation(self.ctx.docs(self.type_alias)) 42 .set_documentation(self.ctx.docs(self.type_alias))
42 .set_deprecated( 43 .set_deprecated(
43 self.ctx.is_deprecated(self.type_alias) 44 self.ctx.is_deprecated(self.type_alias)
44 || self.ctx.is_deprecated_assoc_item(self.type_alias), 45 || self.ctx.is_deprecated_assoc_item(self.type_alias),
45 ) 46 )
46 .detail(detail) 47 .detail(detail);
47 .build();
48 48
49 Some(item) 49 Some(item.build())
50 } 50 }
51 51
52 fn name(&self) -> Option<String> { 52 fn name(&self) -> Option<String> {