aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/generate_from_impl_for_enum.rs61
-rw-r--r--crates/assists/src/utils.rs14
2 files changed, 30 insertions, 45 deletions
diff --git a/crates/assists/src/handlers/generate_from_impl_for_enum.rs b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
index f6febd3aa..fac2447c9 100644
--- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
@@ -1,15 +1,9 @@
1use ast::GenericParamsOwner;
2use ide_db::helpers::FamousDefs; 1use ide_db::helpers::FamousDefs;
3use ide_db::RootDatabase; 2use ide_db::RootDatabase;
4use itertools::Itertools; 3use syntax::ast::{self, AstNode, NameOwner};
5use stdx::format_to;
6use syntax::{
7 ast::{self, AstNode, NameOwner},
8 SmolStr,
9};
10use test_utils::mark; 4use test_utils::mark;
11 5
12use crate::{AssistContext, AssistId, AssistKind, Assists}; 6use crate::{AssistContext, AssistId, AssistKind, Assists, utils::generate_trait_impl_text};
13 7
14// Assist: generate_from_impl_for_enum 8// Assist: generate_from_impl_for_enum
15// 9//
@@ -31,8 +25,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
31pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 25pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32 let variant = ctx.find_node_at_offset::<ast::Variant>()?; 26 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
33 let variant_name = variant.name()?; 27 let variant_name = variant.name()?;
34 let enum_name = variant.parent_enum().name()?; 28 let enum_ = ast::Adt::Enum(variant.parent_enum());
35 let enum_type_params = variant.parent_enum().generic_param_list();
36 let (field_name, field_type) = match variant.kind() { 29 let (field_name, field_type) = match variant.kind() {
37 ast::StructKind::Tuple(field_list) => { 30 ast::StructKind::Tuple(field_list) => {
38 if field_list.fields().count() != 1 { 31 if field_list.fields().count() != 1 {
@@ -62,49 +55,27 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext
62 target, 55 target,
63 |edit| { 56 |edit| {
64 let start_offset = variant.parent_enum().syntax().text_range().end(); 57 let start_offset = variant.parent_enum().syntax().text_range().end();
65 let mut buf = String::from("\n\nimpl"); 58 let from_trait = format!("From<{}>", field_type.syntax());
66 if let Some(type_params) = &enum_type_params { 59 let impl_code = if let Some(name) = field_name {
67 format_to!(buf, "{}", type_params.syntax()); 60 format!(
68 } 61 r#" fn from({0}: {1}) -> Self {{
69 format_to!(buf, " From<{}> for {}", field_type.syntax(), enum_name);
70 if let Some(type_params) = enum_type_params {
71 let lifetime_params = type_params
72 .lifetime_params()
73 .filter_map(|it| it.lifetime())
74 .map(|it| SmolStr::from(it.text()));
75 let type_params = type_params
76 .type_params()
77 .filter_map(|it| it.name())
78 .map(|it| SmolStr::from(it.text()));
79
80 let generic_params = lifetime_params.chain(type_params).format(", ");
81 format_to!(buf, "<{}>", generic_params)
82 }
83 if let Some(name) = field_name {
84 format_to!(
85 buf,
86 r#" {{
87 fn from({0}: {1}) -> Self {{
88 Self::{2} {{ {0} }} 62 Self::{2} {{ {0} }}
89 }} 63 }}"#,
90}}"#,
91 name.text(), 64 name.text(),
92 field_type.syntax(), 65 field_type.syntax(),
93 variant_name, 66 variant_name,
94 ); 67 )
95 } else { 68 } else {
96 format_to!( 69 format!(
97 buf, 70 r#" fn from(v: {}) -> Self {{
98 r#" {{
99 fn from(v: {}) -> Self {{
100 Self::{}(v) 71 Self::{}(v)
101 }} 72 }}"#,
102}}"#,
103 field_type.syntax(), 73 field_type.syntax(),
104 variant_name, 74 variant_name,
105 ); 75 )
106 } 76 };
107 edit.insert(start_offset, buf); 77 let from_impl = generate_trait_impl_text(&enum_, &from_trait, &impl_code);
78 edit.insert(start_offset, from_impl);
108 }, 79 },
109 ) 80 )
110} 81}
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index 5dd32aef1..69c107f63 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -367,6 +367,16 @@ pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Opti
367// Generates the surrounding `impl Type { <code> }` including type and lifetime 367// Generates the surrounding `impl Type { <code> }` including type and lifetime
368// parameters 368// parameters
369pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String { 369pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
370 generate_impl_text_inner(adt, None, code)
371}
372
373// Generates the surrounding `impl <trait> for Type { <code> }` including type
374// and lifetime parameters
375pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &str) -> String {
376 generate_impl_text_inner(adt, Some(trait_text), code)
377}
378
379fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str) -> String {
370 let type_params = adt.generic_param_list(); 380 let type_params = adt.generic_param_list();
371 let mut buf = String::with_capacity(code.len()); 381 let mut buf = String::with_capacity(code.len());
372 buf.push_str("\n\nimpl"); 382 buf.push_str("\n\nimpl");
@@ -374,6 +384,10 @@ pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
374 format_to!(buf, "{}", type_params.syntax()); 384 format_to!(buf, "{}", type_params.syntax());
375 } 385 }
376 buf.push(' '); 386 buf.push(' ');
387 if let Some(trait_text) = trait_text {
388 buf.push_str(trait_text);
389 buf.push_str(" for ");
390 }
377 buf.push_str(adt.name().unwrap().text()); 391 buf.push_str(adt.name().unwrap().text());
378 if let Some(type_params) = type_params { 392 if let Some(type_params) = type_params {
379 let lifetime_params = type_params 393 let lifetime_params = type_params