From fee05b0491a71775c4319ce8f76641382f840770 Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 14:27:38 +0200 Subject: use Self instead of enum name --- crates/assists/src/handlers/generate_from_impl_for_enum.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 d9af6ab11..71897e6eb 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs @@ -56,7 +56,7 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext impl From<{0}> for {1} {{ fn from(v: {0}) -> Self {{ - {1}::{2}(v) + Self::{2}(v) }} }}"#, path.syntax(), @@ -106,7 +106,7 @@ mod tests { impl From for A { fn from(v: u32) -> Self { - A::One(v) + Self::One(v) } }"#, ); @@ -121,7 +121,7 @@ impl From for A { impl From for A { fn from(v: foo::bar::baz::Boo) -> Self { - A::One(v) + Self::One(v) } }"#, ); @@ -157,7 +157,7 @@ enum A { $0One(u32), } impl From for A { fn from(v: u32) -> Self { - A::One(v) + Self::One(v) } } "#, @@ -183,7 +183,7 @@ pub trait From { impl From for A { fn from(v: u32) -> Self { - A::One(v) + Self::One(v) } } -- cgit v1.2.3 From e63116c74f79a7909998b27615a308268f9093d6 Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 14:29:26 +0200 Subject: allow any field type --- .../src/handlers/generate_from_impl_for_enum.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 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 71897e6eb..ac9806368 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs @@ -34,10 +34,6 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext return None; } let field_type = field_list.fields().next()?.ty()?; - let path = match field_type { - ast::Type::PathType(it) => it, - _ => return None, - }; if existing_from_impl(&ctx.sema, &variant).is_some() { mark::hit!(test_add_from_impl_already_exists); @@ -59,7 +55,7 @@ impl From<{0}> for {1} {{ Self::{2}(v) }} }}"#, - path.syntax(), + field_type.syntax(), enum_name, variant_name ); @@ -195,6 +191,21 @@ impl From for A { pub trait From { fn from(T) -> Self; +}"#, + ); + } + + #[test] + fn test_add_from_impl_static_str() { + check_assist( + generate_from_impl_for_enum, + "enum A { $0One(&'static str) }", + r#"enum A { One(&'static str) } + +impl From<&'static str> for A { + fn from(v: &'static str) -> Self { + Self::One(v) + } }"#, ); } -- cgit v1.2.3 From 3a4d273ac2506fe5ab2ff2861e5ae702ab44eafe Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 14:46:28 +0200 Subject: handle generic enums --- .../src/handlers/generate_from_impl_for_enum.rs | 66 +++++++++++++++++++--- 1 file 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 @@ +use ast::GenericParamsOwner; use ide_db::helpers::FamousDefs; use ide_db::RootDatabase; -use syntax::ast::{self, AstNode, NameOwner}; +use itertools::Itertools; +use stdx::format_to; +use syntax::{SmolStr, ast::{self, AstNode, NameOwner}}; use test_utils::mark; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -26,6 +29,7 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext let variant = ctx.find_node_at_offset::()?; let variant_name = variant.name()?; let enum_name = variant.parent_enum().name()?; + let enum_type_params = variant.parent_enum().generic_param_list(); let field_list = match variant.kind() { ast::StructKind::Tuple(field_list) => field_list, _ => return None, @@ -47,17 +51,33 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext target, |edit| { let start_offset = variant.parent_enum().syntax().text_range().end(); - let buf = format!( - r#" + let mut buf = String::from("\n\nimpl"); + if let Some(type_params) = &enum_type_params { + format_to!(buf, "{}", type_params.syntax()); + } + format_to!(buf, " From<{}> for {}", field_type.syntax(), enum_name); + if let Some(type_params) = enum_type_params { + let lifetime_params = type_params + .lifetime_params() + .filter_map(|it| it.lifetime()) + .map(|it| SmolStr::from(it.text())); + let type_params = type_params + .type_params() + .filter_map(|it| it.name()) + .map(|it| SmolStr::from(it.text())); -impl From<{0}> for {1} {{ - fn from(v: {0}) -> Self {{ - Self::{2}(v) + let generic_params = lifetime_params.chain(type_params).format(", "); + format_to!(buf, "<{}>", generic_params) + } + format_to!( + buf, + r#" {{ + fn from(v: {}) -> Self {{ + Self::{}(v) }} }}"#, field_type.syntax(), - enum_name, - variant_name + variant_name, ); edit.insert(start_offset, buf); }, @@ -206,6 +226,36 @@ impl From<&'static str> for A { fn from(v: &'static str) -> Self { Self::One(v) } +}"#, + ); + } + + #[test] + fn test_add_from_impl_generic_enum() { + check_assist( + generate_from_impl_for_enum, + "enum Generic { $0One(T), Two(U) }", + r#"enum Generic { One(T), Two(U) } + +impl From for Generic { + fn from(v: T) -> Self { + Self::One(v) + } +}"#, + ); + } + + #[test] + fn test_add_from_impl_with_lifetime() { + check_assist( + generate_from_impl_for_enum, + "enum Generic<'a> { $0One(&'a i32) }", + r#"enum Generic<'a> { One(&'a i32) } + +impl<'a> From<&'a i32> for Generic<'a> { + fn from(v: &'a i32) -> Self { + Self::One(v) + } }"#, ); } -- cgit v1.2.3 From 6799088579fec4400eee897aba13e9d6a3ac8f29 Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 14:46:41 +0200 Subject: update doc --- crates/assists/src/handlers/generate_from_impl_for_enum.rs | 2 +- crates/assists/src/tests/generated.rs | 2 +- 2 files changed, 2 insertions(+), 2 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 8e68ebc7a..95dc9c34a 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs @@ -21,7 +21,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // // impl From for A { // fn from(v: u32) -> Self { -// A::One(v) +// Self::One(v) // } // } // ``` diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index 6f2b22bc2..0516deaff 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs @@ -499,7 +499,7 @@ enum A { One(u32) } impl From for A { fn from(v: u32) -> Self { - A::One(v) + Self::One(v) } } "#####, -- cgit v1.2.3 From 375c13cd44a4aef7f7c99269bd621017ee9d7aeb Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 14:57:06 +0200 Subject: make it work for record-style variants --- .../src/handlers/generate_from_impl_for_enum.rs | 60 +++++++++++++++++----- 1 file changed, 46 insertions(+), 14 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 95dc9c34a..c28eeff51 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs @@ -30,14 +30,22 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext let variant_name = variant.name()?; let enum_name = variant.parent_enum().name()?; let enum_type_params = variant.parent_enum().generic_param_list(); - let field_list = match variant.kind() { - ast::StructKind::Tuple(field_list) => field_list, - _ => return None, + let (field_name, field_type) = match variant.kind() { + ast::StructKind::Tuple(field_list) => { + if field_list.fields().count() != 1 { + return None; + } + (None, field_list.fields().next()?.ty()?) + } + ast::StructKind::Record(field_list) => { + if field_list.fields().count() != 1 { + return None; + } + let field = field_list.fields().next()?; + (Some(field.name()?), field.ty()?) + } + ast::StructKind::Unit => return None, }; - if field_list.fields().count() != 1 { - return None; - } - let field_type = field_list.fields().next()?.ty()?; if existing_from_impl(&ctx.sema, &variant).is_some() { mark::hit!(test_add_from_impl_already_exists); @@ -69,16 +77,30 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext let generic_params = lifetime_params.chain(type_params).format(", "); format_to!(buf, "<{}>", generic_params) } - format_to!( - buf, - r#" {{ + if let Some(name) = field_name { + format_to!( + buf, + r#" {{ + fn from({0}: {1}) -> Self {{ + Self::{2} {{ {0} }} + }} +}}"#, + name.text(), + field_type.syntax(), + variant_name, + ); + } else { + format_to!( + buf, + r#" {{ fn from(v: {}) -> Self {{ Self::{}(v) }} }}"#, - field_type.syntax(), - variant_name, - ); + field_type.syntax(), + variant_name, + ); + } edit.insert(start_offset, buf); }, ) @@ -161,7 +183,17 @@ impl From for A { #[test] fn test_add_from_impl_struct_variant() { - check_not_applicable("enum A { $0One { x: u32 } }"); + check_assist( + generate_from_impl_for_enum, + "enum A { $0One { x: u32 } }", + r#"enum A { One { x: u32 } } + +impl From for A { + fn from(x: u32) -> Self { + Self::One { x } + } +}"#, + ); } #[test] -- cgit v1.2.3 From b07f530e3ae025c57b2b64e8ebb2852e60bced7b Mon Sep 17 00:00:00 2001 From: Domantas Jadenkus Date: Sat, 13 Feb 2021 15:34:40 +0200 Subject: cargo fmt --- crates/assists/src/handlers/generate_from_impl_for_enum.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 c28eeff51..f6febd3aa 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs @@ -3,7 +3,10 @@ use ide_db::helpers::FamousDefs; use ide_db::RootDatabase; use itertools::Itertools; use stdx::format_to; -use syntax::{SmolStr, ast::{self, AstNode, NameOwner}}; +use syntax::{ + ast::{self, AstNode, NameOwner}, + SmolStr, +}; use test_utils::mark; use crate::{AssistContext, AssistId, AssistKind, Assists}; -- cgit v1.2.3