diff options
-rw-r--r-- | crates/assists/src/handlers/generate_from_impl_for_enum.rs | 61 | ||||
-rw-r--r-- | crates/assists/src/utils.rs | 14 |
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 @@ | |||
1 | use ast::GenericParamsOwner; | ||
2 | use ide_db::helpers::FamousDefs; | 1 | use ide_db::helpers::FamousDefs; |
3 | use ide_db::RootDatabase; | 2 | use ide_db::RootDatabase; |
4 | use itertools::Itertools; | 3 | use syntax::ast::{self, AstNode, NameOwner}; |
5 | use stdx::format_to; | ||
6 | use syntax::{ | ||
7 | ast::{self, AstNode, NameOwner}, | ||
8 | SmolStr, | ||
9 | }; | ||
10 | use test_utils::mark; | 4 | use test_utils::mark; |
11 | 5 | ||
12 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 6 | use 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}; | |||
31 | pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(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 |
369 | pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String { | 369 | pub(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 | ||
375 | pub(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 | |||
379 | fn 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 |