diff options
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 87 |
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#" |
841 | fn with_args(x: i32, y: String) {} | 844 | fn with_args(x: i32, y: String) {} |
@@ -845,7 +848,6 @@ fn main() { with_<|> } | |||
845 | fn with_args(x: i32, y: String) {} | 848 | fn with_args(x: i32, y: String) {} |
846 | fn main() { with_args($0) } | 849 | fn 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#" | ||
918 | enum E { Var(i32) } | ||
919 | fn main() { | ||
920 | match E::Var(92) { | ||
921 | E::<|>(92) => (), | ||
922 | } | ||
923 | } | ||
924 | "#, | ||
925 | r#" | ||
926 | enum E { Var(i32) } | ||
927 | fn 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#" | ||
1167 | struct Foo; | ||
1168 | fn 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!", |