Skip to content

Commit a5e8dfd

Browse files
committed
Add parens for enums
1 parent b1cf95f commit a5e8dfd

File tree

4 files changed

+175
-46
lines changed

4 files changed

+175
-46
lines changed

crates/ra_ide/src/completion/complete_dot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
6161
&& ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m))
6262
&& seen_methods.insert(func.name(ctx.db))
6363
{
64-
acc.add_function(ctx, func);
64+
acc.add_function(ctx, func, None);
6565
}
6666
None::<()>
6767
});

crates/ra_ide/src/completion/complete_path.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
3838
hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
3939
if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
4040
for variant in e.variants(ctx.db) {
41-
acc.add_enum_variant(ctx, variant);
41+
acc.add_enum_variant(ctx, variant, None);
4242
}
4343
}
4444
let ty = match def {
@@ -58,7 +58,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
5858
match item {
5959
hir::AssocItem::Function(func) => {
6060
if !func.has_self_param(ctx.db) {
61-
acc.add_function(ctx, func);
61+
acc.add_function(ctx, func, None);
6262
}
6363
}
6464
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
@@ -87,7 +87,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
8787
match item {
8888
hir::AssocItem::Function(func) => {
8989
if !func.has_self_param(ctx.db) {
90-
acc.add_function(ctx, func);
90+
acc.add_function(ctx, func, None);
9191
}
9292
}
9393
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
@@ -355,15 +355,17 @@ mod tests {
355355
@r###"
356356
[
357357
CompletionItem {
358-
label: "Bar",
358+
label: "Bar(…)",
359359
source_range: [116; 116),
360360
delete: [116; 116),
361-
insert: "Bar",
361+
insert: "Bar($0)",
362362
kind: EnumVariant,
363+
lookup: "Bar",
363364
detail: "(i32)",
364365
documentation: Documentation(
365366
"Bar Variant with i32",
366367
),
368+
trigger_call_info: true,
367369
},
368370
CompletionItem {
369371
label: "Foo",
@@ -403,15 +405,17 @@ mod tests {
403405
@r###"
404406
[
405407
CompletionItem {
406-
label: "Bar",
408+
label: "Bar(…)",
407409
source_range: [180; 180),
408410
delete: [180; 180),
409-
insert: "Bar",
411+
insert: "Bar($0)",
410412
kind: EnumVariant,
413+
lookup: "Bar",
411414
detail: "(i32, u32)",
412415
documentation: Documentation(
413416
"Bar Variant with i32 and u32",
414417
),
418+
trigger_call_info: true,
415419
},
416420
CompletionItem {
417421
label: "Foo",
@@ -425,15 +429,17 @@ mod tests {
425429
),
426430
},
427431
CompletionItem {
428-
label: "S",
432+
label: "S(…)",
429433
source_range: [180; 180),
430434
delete: [180; 180),
431-
insert: "S",
435+
insert: "S($0)",
432436
kind: EnumVariant,
437+
lookup: "S",
433438
detail: "(S)",
434439
documentation: Documentation(
435440
"",
436441
),
442+
trigger_call_info: true,
437443
},
438444
]
439445
"###

crates/ra_ide/src/completion/complete_pattern.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ mod tests {
7777
delete: [246; 246),
7878
insert: "X",
7979
kind: EnumVariant,
80+
detail: "()",
8081
},
8182
CompletionItem {
8283
label: "Z",

crates/ra_ide/src/completion/presentation.rs

Lines changed: 158 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,16 @@ impl Completions {
5757
let kind = match resolution {
5858
ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module,
5959
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));
6161
}
6262
ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct,
6363
// FIXME: add CompletionItemKind::Union
6464
ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct,
6565
ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum,
6666

67-
ScopeDef::ModuleDef(EnumVariant(..)) => CompletionItemKind::EnumVariant,
67+
ScopeDef::ModuleDef(EnumVariant(var)) => {
68+
return self.add_enum_variant(ctx, *var, Some(local_name));
69+
}
6870
ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const,
6971
ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static,
7072
ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait,
@@ -125,10 +127,6 @@ impl Completions {
125127
completion_item.kind(kind).set_documentation(docs).add_to(self)
126128
}
127129

128-
pub(crate) fn add_function(&mut self, ctx: &CompletionContext, func: hir::Function) {
129-
self.add_function_with_name(ctx, None, func)
130-
}
131-
132130
fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str {
133131
let mut votes = [0, 0, 0];
134132
for (idx, s) in docs.match_indices(&macro_name) {
@@ -187,15 +185,15 @@ impl Completions {
187185
self.add(builder);
188186
}
189187

190-
fn add_function_with_name(
188+
pub(crate) fn add_function(
191189
&mut self,
192190
ctx: &CompletionContext,
193-
name: Option<String>,
194191
func: hir::Function,
192+
local_name: Option<String>,
195193
) {
196194
let has_self_param = func.has_self_param(ctx.db);
197195

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());
199197
let ast_node = func.source(ctx.db).value;
200198
let function_signature = FunctionSignature::from(&ast_node);
201199

@@ -217,7 +215,7 @@ impl Completions {
217215
.cloned()
218216
.collect();
219217

220-
builder = builder.add_call_parens(ctx, name, params);
218+
builder = builder.add_call_parens(ctx, name, Params::Named(params));
221219

222220
self.add(builder)
223221
}
@@ -254,14 +252,20 @@ impl Completions {
254252
.add_to(self);
255253
}
256254

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+
) {
258261
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());
260263
let detail_types = variant
261264
.fields(ctx.db)
262265
.into_iter()
263266
.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 {
265269
StructKind::Tuple | StructKind::Unit => detail_types
266270
.map(|(_, t)| t.display(ctx.db).to_string())
267271
.sep_by(", ")
@@ -273,22 +277,42 @@ impl Completions {
273277
.surround_with("{ ", " }")
274278
.to_string(),
275279
};
276-
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
277-
.kind(CompletionItemKind::EnumVariant)
278-
.set_documentation(variant.docs(ctx.db))
279-
.set_deprecated(is_deprecated)
280-
.detail(detail)
281-
.add_to(self);
280+
let mut res =
281+
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
282+
.kind(CompletionItemKind::EnumVariant)
283+
.set_documentation(variant.docs(ctx.db))
284+
.set_deprecated(is_deprecated)
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
282311
}
283312
}
284313

285314
impl Builder {
286-
fn add_call_parens(
287-
mut self,
288-
ctx: &CompletionContext,
289-
name: String,
290-
params: Vec<String>,
291-
) -> Builder {
315+
fn add_call_parens(mut self, ctx: &CompletionContext, name: String, params: Params) -> Builder {
292316
if !ctx.config.add_call_parenthesis {
293317
return self;
294318
}
@@ -302,15 +326,16 @@ impl Builder {
302326
(format!("{}()$0", name), format!("{}()", name))
303327
} else {
304328
self = self.trigger_call_info();
305-
let snippet = if ctx.config.add_call_argument_snippets {
306-
let function_params_snippet = params
307-
.iter()
308-
.enumerate()
309-
.map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name))
310-
.sep_by(", ");
311-
format!("{}({})$0", name, function_params_snippet)
312-
} else {
313-
format!("{}($0)", name)
329+
let snippet = match (ctx.config.add_call_argument_snippets, params) {
330+
(true, Params::Named(params)) => {
331+
let function_params_snippet = params
332+
.iter()
333+
.enumerate()
334+
.map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name))
335+
.sep_by(", ");
336+
format!("{}({})$0", name, function_params_snippet)
337+
}
338+
_ => format!("{}($0)", name),
314339
};
315340

316341
(snippet, format!("{}(…)", name))
@@ -385,12 +410,14 @@ mod tests {
385410
@r###"
386411
[
387412
CompletionItem {
388-
label: "Foo",
413+
label: "Foo(…)",
389414
source_range: [115; 117),
390415
delete: [115; 117),
391-
insert: "Foo",
416+
insert: "Foo($0)",
392417
kind: EnumVariant,
418+
lookup: "Foo",
393419
detail: "(i32, i32)",
420+
trigger_call_info: true,
394421
},
395422
]"###
396423
);
@@ -564,6 +591,101 @@ mod tests {
564591
);
565592
}
566593

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+
567689
#[test]
568690
fn arg_snippets_for_method_call() {
569691
assert_debug_snapshot!(

0 commit comments

Comments
 (0)