aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDomantas Jadenkus <[email protected]>2021-02-14 17:26:37 +0000
committerDomantas Jadenkus <[email protected]>2021-02-27 10:06:00 +0000
commite0f08fcc20ba18a8225b5c591b8b5429090d1943 (patch)
tree6c1a95fe7873db8dc44ff624ac2cba70325da383
parent642786986ff21f33d3a08191d7c19cccf97d25e2 (diff)
add generate_enum_as_method assist
-rw-r--r--crates/ide_assists/src/handlers/generate_enum_match_method.rs124
-rw-r--r--crates/ide_assists/src/lib.rs1
-rw-r--r--crates/ide_assists/src/tests/generated.rs29
3 files changed, 154 insertions, 0 deletions
diff --git a/crates/ide_assists/src/handlers/generate_enum_match_method.rs b/crates/ide_assists/src/handlers/generate_enum_match_method.rs
index b271b48b6..45a08acad 100644
--- a/crates/ide_assists/src/handlers/generate_enum_match_method.rs
+++ b/crates/ide_assists/src/handlers/generate_enum_match_method.rs
@@ -145,6 +145,79 @@ pub(crate) fn generate_enum_into_method(acc: &mut Assists, ctx: &AssistContext)
145 ) 145 )
146} 146}
147 147
148// Assist: generate_enum_as_method
149//
150// Generate an `as_` method for an enum variant.
151//
152// ```
153// enum Value {
154// Number(i32),
155// Text(String)$0,
156// }
157// ```
158// ->
159// ```
160// enum Value {
161// Number(i32),
162// Text(String),
163// }
164//
165// impl Value {
166// fn as_text(&self) -> Option<&String> {
167// if let Self::Text(v) = self {
168// Some(v)
169// } else {
170// None
171// }
172// }
173// }
174// ```
175pub(crate) fn generate_enum_as_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
176 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
177 let variant_name = variant.name()?;
178 let parent_enum = ast::Adt::Enum(variant.parent_enum());
179 let variant_kind = variant_kind(&variant);
180
181 let fn_name = format!("as_{}", &to_lower_snake_case(variant_name.text()));
182
183 // Return early if we've found an existing new fn
184 let impl_def = find_struct_impl(
185 &ctx,
186 &parent_enum,
187 &fn_name,
188 )?;
189
190 let field_type = variant_kind.single_field_type()?;
191 let (pattern_suffix, bound_name) = variant_kind.binding_pattern()?;
192
193 let target = variant.syntax().text_range();
194 acc.add(
195 AssistId("generate_enum_as_method", AssistKind::Generate),
196 "Generate an `as_` method for an enum variant",
197 target,
198 |builder| {
199 let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
200 let method = format!(
201 " {}fn {}(&self) -> Option<&{}> {{
202 if let Self::{}{} = self {{
203 Some({})
204 }} else {{
205 None
206 }}
207 }}",
208 vis,
209 fn_name,
210 field_type.syntax(),
211 variant_name,
212 pattern_suffix,
213 bound_name,
214 );
215
216 add_method_to_adt(builder, &parent_enum, impl_def, &method);
217 },
218 )
219}
220
148fn add_method_to_adt( 221fn add_method_to_adt(
149 builder: &mut AssistBuilder, 222 builder: &mut AssistBuilder,
150 adt: &ast::Adt, 223 adt: &ast::Adt,
@@ -530,4 +603,55 @@ impl Value {
530}"#, 603}"#,
531 ); 604 );
532 } 605 }
606
607 #[test]
608 fn test_generate_enum_as_tuple_variant() {
609 check_assist(
610 generate_enum_as_method,
611 r#"
612enum Value {
613 Number(i32),
614 Text(String)$0,
615}"#,
616 r#"enum Value {
617 Number(i32),
618 Text(String),
619}
620
621impl Value {
622 fn as_text(&self) -> Option<&String> {
623 if let Self::Text(v) = self {
624 Some(v)
625 } else {
626 None
627 }
628 }
629}"#,
630 );
631 }
632
633 #[test]
634 fn test_generate_enum_as_record_variant() {
635 check_assist(
636 generate_enum_as_method,
637 r#"enum Value {
638 Number(i32),
639 Text { text: String }$0,
640}"#,
641 r#"enum Value {
642 Number(i32),
643 Text { text: String },
644}
645
646impl Value {
647 fn as_text(&self) -> Option<&String> {
648 if let Self::Text { text } = self {
649 Some(text)
650 } else {
651 None
652 }
653 }
654}"#,
655 );
656 }
533} 657}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 2ce59e39a..84ac928e9 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -191,6 +191,7 @@ mod handlers {
191 generate_derive::generate_derive, 191 generate_derive::generate_derive,
192 generate_enum_match_method::generate_enum_is_method, 192 generate_enum_match_method::generate_enum_is_method,
193 generate_enum_match_method::generate_enum_into_method, 193 generate_enum_match_method::generate_enum_into_method,
194 generate_enum_match_method::generate_enum_as_method,
194 generate_from_impl_for_enum::generate_from_impl_for_enum, 195 generate_from_impl_for_enum::generate_from_impl_for_enum,
195 generate_function::generate_function, 196 generate_function::generate_function,
196 generate_getter::generate_getter, 197 generate_getter::generate_getter,
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 39f48dd76..14b372c62 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -483,6 +483,35 @@ struct Point {
483} 483}
484 484
485#[test] 485#[test]
486fn doctest_generate_enum_as_method() {
487 check_doc_test(
488 "generate_enum_as_method",
489 r#####"
490enum Value {
491 Number(i32),
492 Text(String)$0,
493}
494"#####,
495 r#####"
496enum Value {
497 Number(i32),
498 Text(String),
499}
500
501impl Value {
502 fn as_text(&self) -> Option<&String> {
503 if let Self::Text(v) = self {
504 Some(v)
505 } else {
506 None
507 }
508 }
509}
510"#####,
511 )
512}
513
514#[test]
486fn doctest_generate_enum_into_method() { 515fn doctest_generate_enum_into_method() {
487 check_doc_test( 516 check_doc_test(
488 "generate_enum_into_method", 517 "generate_enum_into_method",