Skip to content

Commit 15d8049

Browse files
committed
Support tuple fields in generate_enum_variant
1 parent bea1fec commit 15d8049

File tree

1 file changed

+111
-4
lines changed

1 file changed

+111
-4
lines changed

crates/ide-assists/src/handlers/generate_enum_variant.rs

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use hir::{HasSource, InFile};
1+
use hir::{HasSource, HirDisplay, InFile};
22
use ide_db::assists::{AssistId, AssistKind};
33
use syntax::{
4-
ast::{self, make},
4+
ast::{self, make, HasArgList},
55
AstNode,
66
};
77

@@ -50,7 +50,7 @@ pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>)
5050
ctx.sema.resolve_path(&path.qualifier()?)
5151
{
5252
let target = path.syntax().text_range();
53-
return add_variant_to_accumulator(acc, ctx, target, e, &name_ref);
53+
return add_variant_to_accumulator(acc, ctx, target, e, &name_ref, &path);
5454
}
5555

5656
None
@@ -62,23 +62,65 @@ fn add_variant_to_accumulator(
6262
target: syntax::TextRange,
6363
adt: hir::Enum,
6464
name_ref: &ast::NameRef,
65+
path: &ast::Path,
6566
) -> Option<()> {
6667
let db = ctx.db();
6768
let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;
6869

69-
let variant = make::variant(make::name(&name_ref.text()), None);
7070
acc.add(
7171
AssistId("generate_enum_variant", AssistKind::Generate),
7272
"Generate variant",
7373
target,
7474
|builder| {
7575
builder.edit_file(file_id.original_file(db));
7676
let node = builder.make_mut(enum_node);
77+
let variant = make_variant(ctx, name_ref, &path);
7778
node.variant_list().map(|it| it.add_variant(variant.clone_for_update()));
7879
},
7980
)
8081
}
8182

83+
fn make_variant(
84+
ctx: &AssistContext<'_>,
85+
name_ref: &ast::NameRef,
86+
path: &ast::Path,
87+
) -> ast::Variant {
88+
let field_list = make_field_list(ctx, path);
89+
make::variant(make::name(&name_ref.text()), field_list)
90+
}
91+
92+
fn make_field_list(ctx: &AssistContext<'_>, path: &ast::Path) -> Option<ast::FieldList> {
93+
let scope = ctx.sema.scope(&path.syntax())?;
94+
if let Some(call_expr) =
95+
path.syntax().parent().and_then(|it| it.parent()).and_then(ast::CallExpr::cast)
96+
{
97+
make_tuple_field_list(call_expr, ctx, &scope)
98+
} else {
99+
None
100+
}
101+
}
102+
103+
fn make_tuple_field_list(
104+
call_expr: ast::CallExpr,
105+
ctx: &AssistContext<'_>,
106+
scope: &hir::SemanticsScope<'_>,
107+
) -> Option<ast::FieldList> {
108+
let args = call_expr.arg_list()?.args();
109+
let tuple_fields = args.map(|arg| {
110+
let ty = expr_ty(ctx, arg, &scope);
111+
make::tuple_field(None, ty)
112+
});
113+
Some(make::tuple_field_list(tuple_fields).into())
114+
}
115+
116+
fn expr_ty(ctx: &AssistContext<'_>, arg: ast::Expr, scope: &hir::SemanticsScope<'_>) -> ast::Type {
117+
let ty = ctx.sema.type_of_expr(&arg).map(|it| it.adjusted());
118+
let text = ty
119+
.and_then(|it| it.display_source_code(ctx.db(), scope.module().into()).ok())
120+
.unwrap_or_else(|| "_".to_string());
121+
make::ty(&text)
122+
}
123+
82124
#[cfg(test)]
83125
mod tests {
84126
use crate::tests::{check_assist, check_assist_not_applicable};
@@ -211,6 +253,71 @@ mod m {
211253
fn main() {
212254
m::Foo::Baz
213255
}
256+
",
257+
)
258+
}
259+
260+
#[test]
261+
fn associated_single_element_tuple() {
262+
check_assist(
263+
generate_enum_variant,
264+
r"
265+
enum Foo {}
266+
fn main() {
267+
Foo::Bar$0(true)
268+
}
269+
",
270+
r"
271+
enum Foo {
272+
Bar(bool),
273+
}
274+
fn main() {
275+
Foo::Bar(true)
276+
}
277+
",
278+
)
279+
}
280+
281+
#[test]
282+
fn associated_single_element_tuple_unknown_type() {
283+
check_assist(
284+
generate_enum_variant,
285+
r"
286+
enum Foo {}
287+
fn main() {
288+
Foo::Bar$0(x)
289+
}
290+
",
291+
r"
292+
enum Foo {
293+
Bar(_),
294+
}
295+
fn main() {
296+
Foo::Bar(x)
297+
}
298+
",
299+
)
300+
}
301+
302+
#[test]
303+
fn associated_multi_element_tuple() {
304+
check_assist(
305+
generate_enum_variant,
306+
r"
307+
struct Struct {}
308+
enum Foo {}
309+
fn main() {
310+
Foo::Bar$0(true, x, Struct {})
311+
}
312+
",
313+
r"
314+
struct Struct {}
315+
enum Foo {
316+
Bar(bool, _, Struct),
317+
}
318+
fn main() {
319+
Foo::Bar(true, x, Struct {})
320+
}
214321
",
215322
)
216323
}

0 commit comments

Comments
 (0)