diff options
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index aada4d025..253848602 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -1,6 +1,6 @@ | |||
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::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; | 3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; |
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; |
@@ -9,7 +9,10 @@ use crate::completion::{ | |||
9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::display::{const_label, macro_label, type_label, FunctionSignature}; | 12 | use crate::{ |
13 | display::{const_label, macro_label, type_label, FunctionSignature}, | ||
14 | RootDatabase, | ||
15 | }; | ||
13 | 16 | ||
14 | impl Completions { | 17 | impl Completions { |
15 | pub(crate) fn add_field( | 18 | pub(crate) fn add_field( |
@@ -104,10 +107,7 @@ impl Completions { | |||
104 | }; | 107 | }; |
105 | 108 | ||
106 | // Add `<>` for generic types | 109 | // Add `<>` for generic types |
107 | if ctx.is_path_type | 110 | if ctx.is_path_type && !ctx.has_type_args && ctx.options.add_call_parenthesis { |
108 | && !ctx.has_type_args | ||
109 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | ||
110 | { | ||
111 | let has_non_default_type_params = match resolution { | 111 | let has_non_default_type_params = match resolution { |
112 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), | 112 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), |
113 | ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), | 113 | ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), |
@@ -212,21 +212,14 @@ impl Completions { | |||
212 | .detail(function_signature.to_string()); | 212 | .detail(function_signature.to_string()); |
213 | 213 | ||
214 | // If not an import, add parenthesis automatically. | 214 | // If not an import, add parenthesis automatically. |
215 | if ctx.use_item_syntax.is_none() | 215 | if ctx.use_item_syntax.is_none() && !ctx.is_call && ctx.options.add_call_parenthesis { |
216 | && !ctx.is_call | ||
217 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | ||
218 | { | ||
219 | tested_by!(inserts_parens_for_function_calls); | 216 | tested_by!(inserts_parens_for_function_calls); |
220 | 217 | ||
221 | let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 { | 218 | let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 { |
222 | (format!("{}()$0", name), format!("{}()", name)) | 219 | (format!("{}()$0", name), format!("{}()", name)) |
223 | } else { | 220 | } else { |
224 | builder = builder.trigger_call_info(); | 221 | builder = builder.trigger_call_info(); |
225 | let snippet = if ctx | 222 | let snippet = if ctx.options.add_call_argument_snippets { |
226 | .db | ||
227 | .feature_flags | ||
228 | .get("completion.insertion.add-argument-snippets") | ||
229 | { | ||
230 | let to_skip = if has_self_param { 1 } else { 0 }; | 223 | let to_skip = if has_self_param { 1 } else { 0 }; |
231 | let function_params_snippet = join( | 224 | let function_params_snippet = join( |
232 | function_signature.parameter_names.iter().skip(to_skip).enumerate().map( | 225 | function_signature.parameter_names.iter().skip(to_skip).enumerate().map( |
@@ -283,8 +276,10 @@ impl Completions { | |||
283 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { | 276 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { |
284 | let is_deprecated = is_deprecated(variant, ctx.db); | 277 | let is_deprecated = is_deprecated(variant, ctx.db); |
285 | let name = variant.name(ctx.db); | 278 | let name = variant.name(ctx.db); |
286 | let detail_types = | 279 | let detail_types = variant |
287 | variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db))); | 280 | .fields(ctx.db) |
281 | .into_iter() | ||
282 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); | ||
288 | let detail = match variant.kind(ctx.db) { | 283 | let detail = match variant.kind(ctx.db) { |
289 | StructKind::Tuple | StructKind::Unit => { | 284 | StructKind::Tuple | StructKind::Unit => { |
290 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) | 285 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) |
@@ -308,7 +303,7 @@ impl Completions { | |||
308 | } | 303 | } |
309 | } | 304 | } |
310 | 305 | ||
311 | fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { | 306 | fn is_deprecated(node: impl HasAttrs, db: &RootDatabase) -> bool { |
312 | node.attrs(db).by_key("deprecated").exists() | 307 | node.attrs(db).by_key("deprecated").exists() |
313 | } | 308 | } |
314 | 309 | ||
@@ -317,12 +312,22 @@ mod tests { | |||
317 | use insta::assert_debug_snapshot; | 312 | use insta::assert_debug_snapshot; |
318 | use test_utils::covers; | 313 | use test_utils::covers; |
319 | 314 | ||
320 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | 315 | use crate::completion::{ |
316 | test_utils::{do_completion, do_completion_with_options}, | ||
317 | CompletionItem, CompletionKind, CompletionOptions, | ||
318 | }; | ||
321 | 319 | ||
322 | fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { | 320 | fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { |
323 | do_completion(ra_fixture, CompletionKind::Reference) | 321 | do_completion(ra_fixture, CompletionKind::Reference) |
324 | } | 322 | } |
325 | 323 | ||
324 | fn do_reference_completion_with_options( | ||
325 | ra_fixture: &str, | ||
326 | options: CompletionOptions, | ||
327 | ) -> Vec<CompletionItem> { | ||
328 | do_completion_with_options(ra_fixture, CompletionKind::Reference, &options) | ||
329 | } | ||
330 | |||
326 | #[test] | 331 | #[test] |
327 | fn enum_detail_includes_names_for_record() { | 332 | fn enum_detail_includes_names_for_record() { |
328 | assert_debug_snapshot!( | 333 | assert_debug_snapshot!( |
@@ -510,6 +515,7 @@ mod tests { | |||
510 | kind: Function, | 515 | kind: Function, |
511 | lookup: "with_args", | 516 | lookup: "with_args", |
512 | detail: "fn with_args(x: i32, y: String)", | 517 | detail: "fn with_args(x: i32, y: String)", |
518 | trigger_call_info: true, | ||
513 | }, | 519 | }, |
514 | ] | 520 | ] |
515 | "### | 521 | "### |
@@ -543,7 +549,7 @@ mod tests { | |||
543 | } | 549 | } |
544 | 550 | ||
545 | #[test] | 551 | #[test] |
546 | fn parens_for_method_call() { | 552 | fn arg_snippets_for_method_call() { |
547 | assert_debug_snapshot!( | 553 | assert_debug_snapshot!( |
548 | do_reference_completion( | 554 | do_reference_completion( |
549 | r" | 555 | r" |
@@ -566,6 +572,42 @@ mod tests { | |||
566 | kind: Method, | 572 | kind: Method, |
567 | lookup: "foo", | 573 | lookup: "foo", |
568 | detail: "fn foo(&self, x: i32)", | 574 | detail: "fn foo(&self, x: i32)", |
575 | trigger_call_info: true, | ||
576 | }, | ||
577 | ] | ||
578 | "### | ||
579 | ) | ||
580 | } | ||
581 | |||
582 | #[test] | ||
583 | fn no_arg_snippets_for_method_call() { | ||
584 | assert_debug_snapshot!( | ||
585 | do_reference_completion_with_options( | ||
586 | r" | ||
587 | struct S {} | ||
588 | impl S { | ||
589 | fn foo(&self, x: i32) {} | ||
590 | } | ||
591 | fn bar(s: &S) { | ||
592 | s.f<|> | ||
593 | } | ||
594 | ", | ||
595 | CompletionOptions { | ||
596 | add_call_argument_snippets: false, | ||
597 | .. Default::default() | ||
598 | } | ||
599 | ), | ||
600 | @r###" | ||
601 | [ | ||
602 | CompletionItem { | ||
603 | label: "foo(…)", | ||
604 | source_range: [171; 172), | ||
605 | delete: [171; 172), | ||
606 | insert: "foo($0)", | ||
607 | kind: Method, | ||
608 | lookup: "foo", | ||
609 | detail: "fn foo(&self, x: i32)", | ||
610 | trigger_call_info: true, | ||
569 | }, | 611 | }, |
570 | ] | 612 | ] |
571 | "### | 613 | "### |
@@ -684,6 +726,7 @@ mod tests { | |||
684 | kind: Function, | 726 | kind: Function, |
685 | lookup: "foo", | 727 | lookup: "foo", |
686 | detail: "fn foo(xs: Ve)", | 728 | detail: "fn foo(xs: Ve)", |
729 | trigger_call_info: true, | ||
687 | }, | 730 | }, |
688 | ] | 731 | ] |
689 | "### | 732 | "### |
@@ -713,6 +756,7 @@ mod tests { | |||
713 | kind: Function, | 756 | kind: Function, |
714 | lookup: "foo", | 757 | lookup: "foo", |
715 | detail: "fn foo(xs: Ve)", | 758 | detail: "fn foo(xs: Ve)", |
759 | trigger_call_info: true, | ||
716 | }, | 760 | }, |
717 | ] | 761 | ] |
718 | "### | 762 | "### |
@@ -741,6 +785,7 @@ mod tests { | |||
741 | kind: Function, | 785 | kind: Function, |
742 | lookup: "foo", | 786 | lookup: "foo", |
743 | detail: "fn foo(xs: Ve)", | 787 | detail: "fn foo(xs: Ve)", |
788 | trigger_call_info: true, | ||
744 | }, | 789 | }, |
745 | ] | 790 | ] |
746 | "### | 791 | "### |
@@ -769,6 +814,7 @@ mod tests { | |||
769 | kind: Function, | 814 | kind: Function, |
770 | lookup: "foo", | 815 | lookup: "foo", |
771 | detail: "fn foo(xs: Ve<i128>)", | 816 | detail: "fn foo(xs: Ve<i128>)", |
817 | trigger_call_info: true, | ||
772 | }, | 818 | }, |
773 | ] | 819 | ] |
774 | "### | 820 | "### |