aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/presentation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r--crates/ra_ide/src/completion/presentation.rs87
1 files changed, 65 insertions, 22 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index bfa7e08be..9a94ff476 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -11,7 +11,7 @@ use crate::{
11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
12 CompletionKind, Completions, 12 CompletionKind, Completions,
13 }, 13 },
14 display::{const_label, macro_label, type_label, FunctionSignature}, 14 display::{const_label, function_declaration, macro_label, type_label},
15 CompletionScore, RootDatabase, 15 CompletionScore, RootDatabase,
16}; 16};
17 17
@@ -79,11 +79,10 @@ impl Completions {
79 return self.add_macro(ctx, Some(local_name), *mac); 79 return self.add_macro(ctx, Some(local_name), *mac);
80 } 80 }
81 ScopeDef::Unknown => { 81 ScopeDef::Unknown => {
82 return self.add(CompletionItem::new( 82 return self.add(
83 CompletionKind::Reference, 83 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name)
84 ctx.source_range(), 84 .kind(CompletionItemKind::UnresolvedReference),
85 local_name, 85 );
86 ));
87 } 86 }
88 }; 87 };
89 88
@@ -196,7 +195,6 @@ impl Completions {
196 195
197 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); 196 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
198 let ast_node = func.source(ctx.db).value; 197 let ast_node = func.source(ctx.db).value;
199 let function_signature = FunctionSignature::from(&ast_node);
200 198
201 let mut builder = 199 let mut builder =
202 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) 200 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
@@ -207,13 +205,14 @@ impl Completions {
207 }) 205 })
208 .set_documentation(func.docs(ctx.db)) 206 .set_documentation(func.docs(ctx.db))
209 .set_deprecated(is_deprecated(func, ctx.db)) 207 .set_deprecated(is_deprecated(func, ctx.db))
210 .detail(function_signature.to_string()); 208 .detail(function_declaration(&ast_node));
211 209
212 let params = function_signature 210 let params = ast_node
213 .parameter_names 211 .param_list()
214 .iter() 212 .into_iter()
215 .skip(if function_signature.has_self_param { 1 } else { 0 }) 213 .flat_map(|it| it.params())
216 .map(|name| name.trim_start_matches('_').into()) 214 .flat_map(|it| it.pat())
215 .map(|pat| pat.to_string().trim_start_matches('_').into())
217 .collect(); 216 .collect();
218 217
219 builder = builder.add_call_parens(ctx, name, Params::Named(params)); 218 builder = builder.add_call_parens(ctx, name, Params::Named(params));
@@ -316,6 +315,7 @@ impl Completions {
316 } 315 }
317 316
318 if variant_kind == StructKind::Tuple { 317 if variant_kind == StructKind::Tuple {
318 mark::hit!(inserts_parens_for_tuple_enums);
319 let params = Params::Anonymous(variant.fields(ctx.db).len()); 319 let params = Params::Anonymous(variant.fields(ctx.db).len());
320 res = res.add_call_parens(ctx, qualified_name, params) 320 res = res.add_call_parens(ctx, qualified_name, params)
321 } 321 }
@@ -329,15 +329,10 @@ pub(crate) fn compute_score(
329 ty: &Type, 329 ty: &Type,
330 name: &str, 330 name: &str,
331) -> Option<CompletionScore> { 331) -> Option<CompletionScore> {
332 // FIXME: this should not fall back to string equality.
333 let ty = &ty.display(ctx.db).to_string();
334 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
335 mark::hit!(record_field_type_match); 333 mark::hit!(record_field_type_match);
336 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
337 ( 335 (struct_field.name(ctx.db).to_string(), struct_field.signature_ty(ctx.db))
338 struct_field.name(ctx.db).to_string(),
339 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
340 )
341 } else if let Some(active_parameter) = &ctx.active_parameter { 336 } else if let Some(active_parameter) = &ctx.active_parameter {
342 mark::hit!(active_param_type_match); 337 mark::hit!(active_param_type_match);
343 (active_parameter.name.clone(), active_parameter.ty.clone()) 338 (active_parameter.name.clone(), active_parameter.ty.clone())
@@ -384,10 +379,17 @@ impl Builder {
384 if !ctx.config.add_call_parenthesis { 379 if !ctx.config.add_call_parenthesis {
385 return self; 380 return self;
386 } 381 }
387 if ctx.use_item_syntax.is_some() || ctx.is_call { 382 if ctx.use_item_syntax.is_some() {
388 mark::hit!(no_parens_in_use_item); 383 mark::hit!(no_parens_in_use_item);
389 return self; 384 return self;
390 } 385 }
386 if ctx.is_pattern_call {
387 mark::hit!(dont_duplicate_pattern_parens);
388 return self;
389 }
390 if ctx.is_call {
391 return self;
392 }
391 393
392 // Don't add parentheses if the expected type is some function reference. 394 // Don't add parentheses if the expected type is some function reference.
393 if let Some(ty) = &ctx.expected_type { 395 if let Some(ty) = &ctx.expected_type {
@@ -492,7 +494,7 @@ mod tests {
492 } 494 }
493 } 495 }
494 496
495 let mut completions = get_all_completion_items(ra_fixture, &CompletionConfig::default()); 497 let mut completions = get_all_completion_items(CompletionConfig::default(), ra_fixture);
496 completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); 498 completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
497 let actual = completions 499 let actual = completions
498 .into_iter() 500 .into_iter()
@@ -836,6 +838,7 @@ fn bar(s: &S) {
836 fn suppress_arg_snippets() { 838 fn suppress_arg_snippets() {
837 mark::check!(suppress_arg_snippets); 839 mark::check!(suppress_arg_snippets);
838 check_edit_with_config( 840 check_edit_with_config(
841 CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
839 "with_args", 842 "with_args",
840 r#" 843 r#"
841fn with_args(x: i32, y: String) {} 844fn with_args(x: i32, y: String) {}
@@ -845,7 +848,6 @@ fn main() { with_<|> }
845fn with_args(x: i32, y: String) {} 848fn with_args(x: i32, y: String) {}
846fn main() { with_args($0) } 849fn main() { with_args($0) }
847"#, 850"#,
848 &CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() },
849 ); 851 );
850 } 852 }
851 853
@@ -866,6 +868,7 @@ fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
866 868
867 #[test] 869 #[test]
868 fn inserts_parens_for_tuple_enums() { 870 fn inserts_parens_for_tuple_enums() {
871 mark::check!(inserts_parens_for_tuple_enums);
869 check_edit( 872 check_edit(
870 "Some", 873 "Some",
871 r#" 874 r#"
@@ -907,6 +910,30 @@ fn main(value: Option<i32>) {
907 } 910 }
908 911
909 #[test] 912 #[test]
913 fn dont_duplicate_pattern_parens() {
914 mark::check!(dont_duplicate_pattern_parens);
915 check_edit(
916 "Var",
917 r#"
918enum E { Var(i32) }
919fn main() {
920 match E::Var(92) {
921 E::<|>(92) => (),
922 }
923}
924"#,
925 r#"
926enum E { Var(i32) }
927fn main() {
928 match E::Var(92) {
929 E::Var(92) => (),
930 }
931}
932"#,
933 );
934 }
935
936 #[test]
910 fn no_call_parens_if_fn_ptr_needed() { 937 fn no_call_parens_if_fn_ptr_needed() {
911 mark::check!(no_call_parens_if_fn_ptr_needed); 938 mark::check!(no_call_parens_if_fn_ptr_needed);
912 check_edit( 939 check_edit(
@@ -1133,6 +1160,22 @@ fn go(world: &WorldSnapshot) { go(w<|>) }
1133 } 1160 }
1134 1161
1135 #[test] 1162 #[test]
1163 fn too_many_arguments() {
1164 mark::check!(too_many_arguments);
1165 check_scores(
1166 r#"
1167struct Foo;
1168fn f(foo: &Foo) { f(foo, w<|>) }
1169"#,
1170 expect![[r#"
1171 st Foo []
1172 fn f(…) []
1173 bn foo []
1174 "#]],
1175 );
1176 }
1177
1178 #[test]
1136 fn guesses_macro_braces() { 1179 fn guesses_macro_braces() {
1137 check_edit( 1180 check_edit(
1138 "vec!", 1181 "vec!",