diff options
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r-- | crates/ide_assists/src/handlers/generate_enum_match_method.rs | 124 | ||||
-rw-r--r-- | crates/ide_assists/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ide_assists/src/tests/generated.rs | 29 |
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 | // ``` | ||
175 | pub(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 | |||
148 | fn add_method_to_adt( | 221 | fn 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#" | ||
612 | enum Value { | ||
613 | Number(i32), | ||
614 | Text(String)$0, | ||
615 | }"#, | ||
616 | r#"enum Value { | ||
617 | Number(i32), | ||
618 | Text(String), | ||
619 | } | ||
620 | |||
621 | impl 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 | |||
646 | impl 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] |
486 | fn doctest_generate_enum_as_method() { | ||
487 | check_doc_test( | ||
488 | "generate_enum_as_method", | ||
489 | r#####" | ||
490 | enum Value { | ||
491 | Number(i32), | ||
492 | Text(String)$0, | ||
493 | } | ||
494 | "#####, | ||
495 | r#####" | ||
496 | enum Value { | ||
497 | Number(i32), | ||
498 | Text(String), | ||
499 | } | ||
500 | |||
501 | impl 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] | ||
486 | fn doctest_generate_enum_into_method() { | 515 | fn doctest_generate_enum_into_method() { |
487 | check_doc_test( | 516 | check_doc_test( |
488 | "generate_enum_into_method", | 517 | "generate_enum_into_method", |