diff options
author | Aleksey Kladov <[email protected]> | 2020-04-03 18:33:12 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-04-03 20:11:05 +0100 |
commit | a5e8dfd0247648d8108386f4f98b3af0e48181f7 (patch) | |
tree | d745850501442345ffee88fa9fa8f32fa155a088 /crates/ra_ide/src/completion/presentation.rs | |
parent | b1cf95f691cf919b3933d659e3f394f0e7f292cd (diff) |
Add parens for enums
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 194 |
1 files changed, 158 insertions, 36 deletions
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( |