diff options
Diffstat (limited to 'crates/ra_ide_api/src/completion/presentation.rs')
-rw-r--r-- | crates/ra_ide_api/src/completion/presentation.rs | 114 |
1 files changed, 109 insertions, 5 deletions
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index 2d670372e..400a266a2 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; | 3 | use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | 7 | ||
8 | use crate::completion::{ | 8 | use crate::completion::{ |
9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 9 | db, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::display::{const_label, function_label, macro_label, type_label}; | 12 | use crate::display::{const_label, function_label, macro_label, type_label}; |
@@ -150,7 +150,8 @@ impl Completions { | |||
150 | }) | 150 | }) |
151 | .set_documentation(func.docs(ctx.db)) | 151 | .set_documentation(func.docs(ctx.db)) |
152 | .detail(detail); | 152 | .detail(detail); |
153 | // If not an import, add parenthesis automatically. | 153 | |
154 | // Add `<>` for generic types | ||
154 | if ctx.use_item_syntax.is_none() | 155 | if ctx.use_item_syntax.is_none() |
155 | && !ctx.is_call | 156 | && !ctx.is_call |
156 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | 157 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") |
@@ -164,11 +165,13 @@ impl Completions { | |||
164 | }; | 165 | }; |
165 | builder = builder.insert_snippet(snippet); | 166 | builder = builder.insert_snippet(snippet); |
166 | } | 167 | } |
168 | |||
167 | self.add(builder) | 169 | self.add(builder) |
168 | } | 170 | } |
169 | 171 | ||
170 | fn add_adt_with_name(&mut self, ctx: &CompletionContext, name: String, adt: hir::Adt) { | 172 | fn add_adt_with_name(&mut self, ctx: &CompletionContext, name: String, adt: hir::Adt) { |
171 | let builder = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name); | 173 | let mut builder = |
174 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()); | ||
172 | 175 | ||
173 | let kind = match adt { | 176 | let kind = match adt { |
174 | hir::Adt::Struct(_) => CompletionItemKind::Struct, | 177 | hir::Adt::Struct(_) => CompletionItemKind::Struct, |
@@ -178,6 +181,17 @@ impl Completions { | |||
178 | }; | 181 | }; |
179 | let docs = adt.docs(ctx.db); | 182 | let docs = adt.docs(ctx.db); |
180 | 183 | ||
184 | // If not an import, add parenthesis automatically. | ||
185 | if ctx.is_path_type | ||
186 | && !ctx.has_type_args | ||
187 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | ||
188 | { | ||
189 | if has_non_default_type_params(adt, ctx.db) { | ||
190 | tested_by!(inserts_angle_brackets_for_generics); | ||
191 | builder = builder.insert_snippet(format!("{}<$0>", name)); | ||
192 | } | ||
193 | } | ||
194 | |||
181 | builder.kind(kind).set_documentation(docs).add_to(self) | 195 | builder.kind(kind).set_documentation(docs).add_to(self) |
182 | } | 196 | } |
183 | 197 | ||
@@ -221,7 +235,6 @@ impl Completions { | |||
221 | .separator(", ") | 235 | .separator(", ") |
222 | .surround_with("(", ")") | 236 | .surround_with("(", ")") |
223 | .to_string(); | 237 | .to_string(); |
224 | |||
225 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 238 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
226 | .kind(CompletionItemKind::EnumVariant) | 239 | .kind(CompletionItemKind::EnumVariant) |
227 | .set_documentation(variant.docs(ctx.db)) | 240 | .set_documentation(variant.docs(ctx.db)) |
@@ -230,6 +243,11 @@ impl Completions { | |||
230 | } | 243 | } |
231 | } | 244 | } |
232 | 245 | ||
246 | fn has_non_default_type_params(adt: hir::Adt, db: &db::RootDatabase) -> bool { | ||
247 | let subst = db.generic_defaults(adt.into()); | ||
248 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
249 | } | ||
250 | |||
233 | #[cfg(test)] | 251 | #[cfg(test)] |
234 | mod tests { | 252 | mod tests { |
235 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 253 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; |
@@ -397,4 +415,90 @@ mod tests { | |||
397 | ]"# | 415 | ]"# |
398 | ); | 416 | ); |
399 | } | 417 | } |
418 | |||
419 | #[test] | ||
420 | fn inserts_angle_brackets_for_generics() { | ||
421 | covers!(inserts_angle_brackets_for_generics); | ||
422 | assert_debug_snapshot!( | ||
423 | do_reference_completion( | ||
424 | r" | ||
425 | struct Vec<T> {} | ||
426 | fn foo(xs: Ve<|>) | ||
427 | " | ||
428 | ), | ||
429 | @r###" | ||
430 | [ | ||
431 | CompletionItem { | ||
432 | label: "Vec", | ||
433 | source_range: [61; 63), | ||
434 | delete: [61; 63), | ||
435 | insert: "Vec<$0>", | ||
436 | kind: Struct, | ||
437 | }, | ||
438 | CompletionItem { | ||
439 | label: "foo", | ||
440 | source_range: [61; 63), | ||
441 | delete: [61; 63), | ||
442 | insert: "foo($0)", | ||
443 | kind: Function, | ||
444 | detail: "fn foo(xs: Ve)", | ||
445 | }, | ||
446 | ] | ||
447 | "### | ||
448 | ); | ||
449 | assert_debug_snapshot!( | ||
450 | do_reference_completion( | ||
451 | r" | ||
452 | struct Vec<T = i128> {} | ||
453 | fn foo(xs: Ve<|>) | ||
454 | " | ||
455 | ), | ||
456 | @r###" | ||
457 | [ | ||
458 | CompletionItem { | ||
459 | label: "Vec", | ||
460 | source_range: [68; 70), | ||
461 | delete: [68; 70), | ||
462 | insert: "Vec", | ||
463 | kind: Struct, | ||
464 | }, | ||
465 | CompletionItem { | ||
466 | label: "foo", | ||
467 | source_range: [68; 70), | ||
468 | delete: [68; 70), | ||
469 | insert: "foo($0)", | ||
470 | kind: Function, | ||
471 | detail: "fn foo(xs: Ve)", | ||
472 | }, | ||
473 | ] | ||
474 | "### | ||
475 | ); | ||
476 | assert_debug_snapshot!( | ||
477 | do_reference_completion( | ||
478 | r" | ||
479 | struct Vec<T> {} | ||
480 | fn foo(xs: Ve<|><i128>) | ||
481 | " | ||
482 | ), | ||
483 | @r###" | ||
484 | [ | ||
485 | CompletionItem { | ||
486 | label: "Vec", | ||
487 | source_range: [61; 63), | ||
488 | delete: [61; 63), | ||
489 | insert: "Vec", | ||
490 | kind: Struct, | ||
491 | }, | ||
492 | CompletionItem { | ||
493 | label: "foo", | ||
494 | source_range: [61; 63), | ||
495 | delete: [61; 63), | ||
496 | insert: "foo($0)", | ||
497 | kind: Function, | ||
498 | detail: "fn foo(xs: Ve<i128>)", | ||
499 | }, | ||
500 | ] | ||
501 | "### | ||
502 | ); | ||
503 | } | ||
400 | } | 504 | } |