diff options
-rw-r--r-- | crates/assists/src/handlers/generate_from_impl_for_enum.rs | 66 |
1 files changed, 58 insertions, 8 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 ac9806368..8e68ebc7a 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | use ast::GenericParamsOwner; | ||
1 | use ide_db::helpers::FamousDefs; | 2 | use ide_db::helpers::FamousDefs; |
2 | use ide_db::RootDatabase; | 3 | use ide_db::RootDatabase; |
3 | use syntax::ast::{self, AstNode, NameOwner}; | 4 | use itertools::Itertools; |
5 | use stdx::format_to; | ||
6 | use syntax::{SmolStr, ast::{self, AstNode, NameOwner}}; | ||
4 | use test_utils::mark; | 7 | use test_utils::mark; |
5 | 8 | ||
6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 9 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
@@ -26,6 +29,7 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext | |||
26 | let variant = ctx.find_node_at_offset::<ast::Variant>()?; | 29 | let variant = ctx.find_node_at_offset::<ast::Variant>()?; |
27 | let variant_name = variant.name()?; | 30 | let variant_name = variant.name()?; |
28 | let enum_name = variant.parent_enum().name()?; | 31 | let enum_name = variant.parent_enum().name()?; |
32 | let enum_type_params = variant.parent_enum().generic_param_list(); | ||
29 | let field_list = match variant.kind() { | 33 | let field_list = match variant.kind() { |
30 | ast::StructKind::Tuple(field_list) => field_list, | 34 | ast::StructKind::Tuple(field_list) => field_list, |
31 | _ => return None, | 35 | _ => return None, |
@@ -47,17 +51,33 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext | |||
47 | target, | 51 | target, |
48 | |edit| { | 52 | |edit| { |
49 | let start_offset = variant.parent_enum().syntax().text_range().end(); | 53 | let start_offset = variant.parent_enum().syntax().text_range().end(); |
50 | let buf = format!( | 54 | let mut buf = String::from("\n\nimpl"); |
51 | r#" | 55 | if let Some(type_params) = &enum_type_params { |
56 | format_to!(buf, "{}", type_params.syntax()); | ||
57 | } | ||
58 | format_to!(buf, " From<{}> for {}", field_type.syntax(), enum_name); | ||
59 | if let Some(type_params) = enum_type_params { | ||
60 | let lifetime_params = type_params | ||
61 | .lifetime_params() | ||
62 | .filter_map(|it| it.lifetime()) | ||
63 | .map(|it| SmolStr::from(it.text())); | ||
64 | let type_params = type_params | ||
65 | .type_params() | ||
66 | .filter_map(|it| it.name()) | ||
67 | .map(|it| SmolStr::from(it.text())); | ||
52 | 68 | ||
53 | impl From<{0}> for {1} {{ | 69 | let generic_params = lifetime_params.chain(type_params).format(", "); |
54 | fn from(v: {0}) -> Self {{ | 70 | format_to!(buf, "<{}>", generic_params) |
55 | Self::{2}(v) | 71 | } |
72 | format_to!( | ||
73 | buf, | ||
74 | r#" {{ | ||
75 | fn from(v: {}) -> Self {{ | ||
76 | Self::{}(v) | ||
56 | }} | 77 | }} |
57 | }}"#, | 78 | }}"#, |
58 | field_type.syntax(), | 79 | field_type.syntax(), |
59 | enum_name, | 80 | variant_name, |
60 | variant_name | ||
61 | ); | 81 | ); |
62 | edit.insert(start_offset, buf); | 82 | edit.insert(start_offset, buf); |
63 | }, | 83 | }, |
@@ -209,4 +229,34 @@ impl From<&'static str> for A { | |||
209 | }"#, | 229 | }"#, |
210 | ); | 230 | ); |
211 | } | 231 | } |
232 | |||
233 | #[test] | ||
234 | fn test_add_from_impl_generic_enum() { | ||
235 | check_assist( | ||
236 | generate_from_impl_for_enum, | ||
237 | "enum Generic<T, U: Clone> { $0One(T), Two(U) }", | ||
238 | r#"enum Generic<T, U: Clone> { One(T), Two(U) } | ||
239 | |||
240 | impl<T, U: Clone> From<T> for Generic<T, U> { | ||
241 | fn from(v: T) -> Self { | ||
242 | Self::One(v) | ||
243 | } | ||
244 | }"#, | ||
245 | ); | ||
246 | } | ||
247 | |||
248 | #[test] | ||
249 | fn test_add_from_impl_with_lifetime() { | ||
250 | check_assist( | ||
251 | generate_from_impl_for_enum, | ||
252 | "enum Generic<'a> { $0One(&'a i32) }", | ||
253 | r#"enum Generic<'a> { One(&'a i32) } | ||
254 | |||
255 | impl<'a> From<&'a i32> for Generic<'a> { | ||
256 | fn from(v: &'a i32) -> Self { | ||
257 | Self::One(v) | ||
258 | } | ||
259 | }"#, | ||
260 | ); | ||
261 | } | ||
212 | } | 262 | } |