diff options
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 24 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_pattern.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 194 |
4 files changed, 175 insertions, 46 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 82ec16913..f433faef3 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -61,7 +61,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
61 | && ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m)) | 61 | && ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m)) |
62 | && seen_methods.insert(func.name(ctx.db)) | 62 | && seen_methods.insert(func.name(ctx.db)) |
63 | { | 63 | { |
64 | acc.add_function(ctx, func); | 64 | acc.add_function(ctx, func, None); |
65 | } | 65 | } |
66 | None::<()> | 66 | None::<()> |
67 | }); | 67 | }); |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 3db17f15f..3ed2ae2b6 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -38,7 +38,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
38 | hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { | 38 | hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { |
39 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { | 39 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { |
40 | for variant in e.variants(ctx.db) { | 40 | for variant in e.variants(ctx.db) { |
41 | acc.add_enum_variant(ctx, variant); | 41 | acc.add_enum_variant(ctx, variant, None); |
42 | } | 42 | } |
43 | } | 43 | } |
44 | let ty = match def { | 44 | let ty = match def { |
@@ -58,7 +58,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
58 | match item { | 58 | match item { |
59 | hir::AssocItem::Function(func) => { | 59 | hir::AssocItem::Function(func) => { |
60 | if !func.has_self_param(ctx.db) { | 60 | if !func.has_self_param(ctx.db) { |
61 | acc.add_function(ctx, func); | 61 | acc.add_function(ctx, func, None); |
62 | } | 62 | } |
63 | } | 63 | } |
64 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | 64 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), |
@@ -87,7 +87,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
87 | match item { | 87 | match item { |
88 | hir::AssocItem::Function(func) => { | 88 | hir::AssocItem::Function(func) => { |
89 | if !func.has_self_param(ctx.db) { | 89 | if !func.has_self_param(ctx.db) { |
90 | acc.add_function(ctx, func); | 90 | acc.add_function(ctx, func, None); |
91 | } | 91 | } |
92 | } | 92 | } |
93 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | 93 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), |
@@ -355,15 +355,17 @@ mod tests { | |||
355 | @r###" | 355 | @r###" |
356 | [ | 356 | [ |
357 | CompletionItem { | 357 | CompletionItem { |
358 | label: "Bar", | 358 | label: "Bar(…)", |
359 | source_range: [116; 116), | 359 | source_range: [116; 116), |
360 | delete: [116; 116), | 360 | delete: [116; 116), |
361 | insert: "Bar", | 361 | insert: "Bar($0)", |
362 | kind: EnumVariant, | 362 | kind: EnumVariant, |
363 | lookup: "Bar", | ||
363 | detail: "(i32)", | 364 | detail: "(i32)", |
364 | documentation: Documentation( | 365 | documentation: Documentation( |
365 | "Bar Variant with i32", | 366 | "Bar Variant with i32", |
366 | ), | 367 | ), |
368 | trigger_call_info: true, | ||
367 | }, | 369 | }, |
368 | CompletionItem { | 370 | CompletionItem { |
369 | label: "Foo", | 371 | label: "Foo", |
@@ -403,15 +405,17 @@ mod tests { | |||
403 | @r###" | 405 | @r###" |
404 | [ | 406 | [ |
405 | CompletionItem { | 407 | CompletionItem { |
406 | label: "Bar", | 408 | label: "Bar(…)", |
407 | source_range: [180; 180), | 409 | source_range: [180; 180), |
408 | delete: [180; 180), | 410 | delete: [180; 180), |
409 | insert: "Bar", | 411 | insert: "Bar($0)", |
410 | kind: EnumVariant, | 412 | kind: EnumVariant, |
413 | lookup: "Bar", | ||
411 | detail: "(i32, u32)", | 414 | detail: "(i32, u32)", |
412 | documentation: Documentation( | 415 | documentation: Documentation( |
413 | "Bar Variant with i32 and u32", | 416 | "Bar Variant with i32 and u32", |
414 | ), | 417 | ), |
418 | trigger_call_info: true, | ||
415 | }, | 419 | }, |
416 | CompletionItem { | 420 | CompletionItem { |
417 | label: "Foo", | 421 | label: "Foo", |
@@ -425,15 +429,17 @@ mod tests { | |||
425 | ), | 429 | ), |
426 | }, | 430 | }, |
427 | CompletionItem { | 431 | CompletionItem { |
428 | label: "S", | 432 | label: "S(…)", |
429 | source_range: [180; 180), | 433 | source_range: [180; 180), |
430 | delete: [180; 180), | 434 | delete: [180; 180), |
431 | insert: "S", | 435 | insert: "S($0)", |
432 | kind: EnumVariant, | 436 | kind: EnumVariant, |
437 | lookup: "S", | ||
433 | detail: "(S)", | 438 | detail: "(S)", |
434 | documentation: Documentation( | 439 | documentation: Documentation( |
435 | "", | 440 | "", |
436 | ), | 441 | ), |
442 | trigger_call_info: true, | ||
437 | }, | 443 | }, |
438 | ] | 444 | ] |
439 | "### | 445 | "### |
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index 1c8b50eec..1b7d3122f 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -77,6 +77,7 @@ mod tests { | |||
77 | delete: [246; 246), | 77 | delete: [246; 246), |
78 | insert: "X", | 78 | insert: "X", |
79 | kind: EnumVariant, | 79 | kind: EnumVariant, |
80 | detail: "()", | ||
80 | }, | 81 | }, |
81 | CompletionItem { | 82 | CompletionItem { |
82 | label: "Z", | 83 | label: "Z", |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 3930316b0..cdfd7bc32 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -57,14 +57,16 @@ impl Completions { | |||
57 | let kind = match resolution { | 57 | let kind = match resolution { |
58 | ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module, | 58 | ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module, |
59 | ScopeDef::ModuleDef(Function(func)) => { | 59 | ScopeDef::ModuleDef(Function(func)) => { |
60 | return self.add_function_with_name(ctx, Some(local_name), *func); | 60 | return self.add_function(ctx, *func, Some(local_name)); |
61 | } | 61 | } |
62 | ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct, | 62 | ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct, |
63 | // FIXME: add CompletionItemKind::Union | 63 | // FIXME: add CompletionItemKind::Union |
64 | ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct, | 64 | ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct, |
65 | ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum, | 65 | ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum, |
66 | 66 | ||
67 | ScopeDef::ModuleDef(EnumVariant(..)) => CompletionItemKind::EnumVariant, | 67 | ScopeDef::ModuleDef(EnumVariant(var)) => { |
68 | return self.add_enum_variant(ctx, *var, Some(local_name)); | ||
69 | } | ||
68 | ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const, | 70 | ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const, |
69 | ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static, | 71 | ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static, |
70 | ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait, | 72 | ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait, |
@@ -125,10 +127,6 @@ impl Completions { | |||
125 | completion_item.kind(kind).set_documentation(docs).add_to(self) | 127 | completion_item.kind(kind).set_documentation(docs).add_to(self) |
126 | } | 128 | } |
127 | 129 | ||
128 | pub(crate) fn add_function(&mut self, ctx: &CompletionContext, func: hir::Function) { | ||
129 | self.add_function_with_name(ctx, None, func) | ||
130 | } | ||
131 | |||
132 | fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str { | 130 | fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str { |
133 | let mut votes = [0, 0, 0]; | 131 | let mut votes = [0, 0, 0]; |
134 | for (idx, s) in docs.match_indices(¯o_name) { | 132 | for (idx, s) in docs.match_indices(¯o_name) { |
@@ -187,15 +185,15 @@ impl Completions { | |||
187 | self.add(builder); | 185 | self.add(builder); |
188 | } | 186 | } |
189 | 187 | ||
190 | fn add_function_with_name( | 188 | pub(crate) fn add_function( |
191 | &mut self, | 189 | &mut self, |
192 | ctx: &CompletionContext, | 190 | ctx: &CompletionContext, |
193 | name: Option<String>, | ||
194 | func: hir::Function, | 191 | func: hir::Function, |
192 | local_name: Option<String>, | ||
195 | ) { | 193 | ) { |
196 | let has_self_param = func.has_self_param(ctx.db); | 194 | let has_self_param = func.has_self_param(ctx.db); |
197 | 195 | ||
198 | let name = name.unwrap_or_else(|| func.name(ctx.db).to_string()); | 196 | let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); |
199 | let ast_node = func.source(ctx.db).value; | 197 | let ast_node = func.source(ctx.db).value; |
200 | let function_signature = FunctionSignature::from(&ast_node); | 198 | let function_signature = FunctionSignature::from(&ast_node); |
201 | 199 | ||
@@ -217,7 +215,7 @@ impl Completions { | |||
217 | .cloned() | 215 | .cloned() |
218 | .collect(); | 216 | .collect(); |
219 | 217 | ||
220 | builder = builder.add_call_parens(ctx, name, params); | 218 | builder = builder.add_call_parens(ctx, name, Params::Named(params)); |
221 | 219 | ||
222 | self.add(builder) | 220 | self.add(builder) |
223 | } | 221 | } |
@@ -254,14 +252,20 @@ impl Completions { | |||
254 | .add_to(self); | 252 | .add_to(self); |
255 | } | 253 | } |
256 | 254 | ||
257 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { | 255 | pub(crate) fn add_enum_variant( |
256 | &mut self, | ||
257 | ctx: &CompletionContext, | ||
258 | variant: hir::EnumVariant, | ||
259 | local_name: Option<String>, | ||
260 | ) { | ||
258 | let is_deprecated = is_deprecated(variant, ctx.db); | 261 | let is_deprecated = is_deprecated(variant, ctx.db); |
259 | let name = variant.name(ctx.db); | 262 | let name = local_name.unwrap_or_else(|| variant.name(ctx.db).to_string()); |
260 | let detail_types = variant | 263 | let detail_types = variant |
261 | .fields(ctx.db) | 264 | .fields(ctx.db) |
262 | .into_iter() | 265 | .into_iter() |
263 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); | 266 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); |
264 | let detail = match variant.kind(ctx.db) { | 267 | let variant_kind = variant.kind(ctx.db); |
268 | let detail = match variant_kind { | ||
265 | StructKind::Tuple | StructKind::Unit => detail_types | 269 | StructKind::Tuple | StructKind::Unit => detail_types |
266 | .map(|(_, t)| t.display(ctx.db).to_string()) | 270 | .map(|(_, t)| t.display(ctx.db).to_string()) |
267 | .sep_by(", ") | 271 | .sep_by(", ") |
@@ -273,22 +277,42 @@ impl Completions { | |||
273 | .surround_with("{ ", " }") | 277 | .surround_with("{ ", " }") |
274 | .to_string(), | 278 | .to_string(), |
275 | }; | 279 | }; |
276 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 280 | let mut res = |
277 | .kind(CompletionItemKind::EnumVariant) | 281 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) |
278 | .set_documentation(variant.docs(ctx.db)) | 282 | .kind(CompletionItemKind::EnumVariant) |
279 | .set_deprecated(is_deprecated) | 283 | .set_documentation(variant.docs(ctx.db)) |
280 | .detail(detail) | 284 | .set_deprecated(is_deprecated) |
281 | .add_to(self); | 285 | .detail(detail); |
286 | |||
287 | if variant_kind == StructKind::Tuple { | ||
288 | let params = Params::Anonymous(variant.fields(ctx.db).len()); | ||
289 | res = res.add_call_parens(ctx, name, params) | ||
290 | } | ||
291 | |||
292 | res.add_to(self); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | enum Params { | ||
297 | Named(Vec<String>), | ||
298 | Anonymous(usize), | ||
299 | } | ||
300 | |||
301 | impl Params { | ||
302 | fn len(&self) -> usize { | ||
303 | match self { | ||
304 | Params::Named(xs) => xs.len(), | ||
305 | Params::Anonymous(len) => *len, | ||
306 | } | ||
307 | } | ||
308 | |||
309 | fn is_empty(&self) -> bool { | ||
310 | self.len() == 0 | ||
282 | } | 311 | } |
283 | } | 312 | } |
284 | 313 | ||
285 | impl Builder { | 314 | impl Builder { |
286 | fn add_call_parens( | 315 | fn add_call_parens(mut self, ctx: &CompletionContext, name: String, params: Params) -> Builder { |
287 | mut self, | ||
288 | ctx: &CompletionContext, | ||
289 | name: String, | ||
290 | params: Vec<String>, | ||
291 | ) -> Builder { | ||
292 | if !ctx.config.add_call_parenthesis { | 316 | if !ctx.config.add_call_parenthesis { |
293 | return self; | 317 | return self; |
294 | } | 318 | } |
@@ -302,15 +326,16 @@ impl Builder { | |||
302 | (format!("{}()$0", name), format!("{}()", name)) | 326 | (format!("{}()$0", name), format!("{}()", name)) |
303 | } else { | 327 | } else { |
304 | self = self.trigger_call_info(); | 328 | self = self.trigger_call_info(); |
305 | let snippet = if ctx.config.add_call_argument_snippets { | 329 | let snippet = match (ctx.config.add_call_argument_snippets, params) { |
306 | let function_params_snippet = params | 330 | (true, Params::Named(params)) => { |
307 | .iter() | 331 | let function_params_snippet = params |
308 | .enumerate() | 332 | .iter() |
309 | .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name)) | 333 | .enumerate() |
310 | .sep_by(", "); | 334 | .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name)) |
311 | format!("{}({})$0", name, function_params_snippet) | 335 | .sep_by(", "); |
312 | } else { | 336 | format!("{}({})$0", name, function_params_snippet) |
313 | format!("{}($0)", name) | 337 | } |
338 | _ => format!("{}($0)", name), | ||
314 | }; | 339 | }; |
315 | 340 | ||
316 | (snippet, format!("{}(…)", name)) | 341 | (snippet, format!("{}(…)", name)) |
@@ -385,12 +410,14 @@ mod tests { | |||
385 | @r###" | 410 | @r###" |
386 | [ | 411 | [ |
387 | CompletionItem { | 412 | CompletionItem { |
388 | label: "Foo", | 413 | label: "Foo(…)", |
389 | source_range: [115; 117), | 414 | source_range: [115; 117), |
390 | delete: [115; 117), | 415 | delete: [115; 117), |
391 | insert: "Foo", | 416 | insert: "Foo($0)", |
392 | kind: EnumVariant, | 417 | kind: EnumVariant, |
418 | lookup: "Foo", | ||
393 | detail: "(i32, i32)", | 419 | detail: "(i32, i32)", |
420 | trigger_call_info: true, | ||
394 | }, | 421 | }, |
395 | ]"### | 422 | ]"### |
396 | ); | 423 | ); |
@@ -565,6 +592,101 @@ mod tests { | |||
565 | } | 592 | } |
566 | 593 | ||
567 | #[test] | 594 | #[test] |
595 | fn inserts_parens_for_tuple_enums() { | ||
596 | assert_debug_snapshot!( | ||
597 | do_reference_completion( | ||
598 | r" | ||
599 | enum Option<T> { Some(T), None } | ||
600 | use Option::*; | ||
601 | fn main() -> Option<i32> { | ||
602 | Som<|> | ||
603 | } | ||
604 | " | ||
605 | ), | ||
606 | @r###" | ||
607 | [ | ||
608 | CompletionItem { | ||
609 | label: "None", | ||
610 | source_range: [144; 147), | ||
611 | delete: [144; 147), | ||
612 | insert: "None", | ||
613 | kind: EnumVariant, | ||
614 | detail: "()", | ||
615 | }, | ||
616 | CompletionItem { | ||
617 | label: "Option", | ||
618 | source_range: [144; 147), | ||
619 | delete: [144; 147), | ||
620 | insert: "Option", | ||
621 | kind: Enum, | ||
622 | }, | ||
623 | CompletionItem { | ||
624 | label: "Some(…)", | ||
625 | source_range: [144; 147), | ||
626 | delete: [144; 147), | ||
627 | insert: "Some($0)", | ||
628 | kind: EnumVariant, | ||
629 | lookup: "Some", | ||
630 | detail: "(T)", | ||
631 | trigger_call_info: true, | ||
632 | }, | ||
633 | CompletionItem { | ||
634 | label: "main()", | ||
635 | source_range: [144; 147), | ||
636 | delete: [144; 147), | ||
637 | insert: "main()$0", | ||
638 | kind: Function, | ||
639 | lookup: "main", | ||
640 | detail: "fn main() -> Option<i32>", | ||
641 | }, | ||
642 | ] | ||
643 | "### | ||
644 | ); | ||
645 | assert_debug_snapshot!( | ||
646 | do_reference_completion( | ||
647 | r" | ||
648 | enum Option<T> { Some(T), None } | ||
649 | use Option::*; | ||
650 | fn main(value: Option<i32>) { | ||
651 | match value { | ||
652 | Som<|> | ||
653 | } | ||
654 | } | ||
655 | " | ||
656 | ), | ||
657 | @r###" | ||
658 | [ | ||
659 | CompletionItem { | ||
660 | label: "None", | ||
661 | source_range: [185; 188), | ||
662 | delete: [185; 188), | ||
663 | insert: "None", | ||
664 | kind: EnumVariant, | ||
665 | detail: "()", | ||
666 | }, | ||
667 | CompletionItem { | ||
668 | label: "Option", | ||
669 | source_range: [185; 188), | ||
670 | delete: [185; 188), | ||
671 | insert: "Option", | ||
672 | kind: Enum, | ||
673 | }, | ||
674 | CompletionItem { | ||
675 | label: "Some(…)", | ||
676 | source_range: [185; 188), | ||
677 | delete: [185; 188), | ||
678 | insert: "Some($0)", | ||
679 | kind: EnumVariant, | ||
680 | lookup: "Some", | ||
681 | detail: "(T)", | ||
682 | trigger_call_info: true, | ||
683 | }, | ||
684 | ] | ||
685 | "### | ||
686 | ); | ||
687 | } | ||
688 | |||
689 | #[test] | ||
568 | fn arg_snippets_for_method_call() { | 690 | fn arg_snippets_for_method_call() { |
569 | assert_debug_snapshot!( | 691 | assert_debug_snapshot!( |
570 | do_reference_completion( | 692 | do_reference_completion( |