1 use ide_db::assists::GroupLabel;
2 use stdx::to_lower_snake_case;
3 use syntax::ast::HasVisibility;
4 use syntax::ast::{self, AstNode, HasName};
7 utils::{add_method_to_adt, find_struct_impl},
8 AssistContext, AssistId, AssistKind, Assists,
11 // Assist: generate_enum_is_method
13 // Generate an `is_` method for this enum variant.
31 // /// Returns `true` if the version is [`Minor`].
33 // /// [`Minor`]: Version::Minor
35 // fn is_minor(&self) -> bool {
36 // matches!(self, Self::Minor)
40 pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
41 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
42 let variant_name = variant.name()?;
43 let parent_enum = ast::Adt::Enum(variant.parent_enum());
44 let pattern_suffix = match variant.kind() {
45 ast::StructKind::Record(_) => " { .. }",
46 ast::StructKind::Tuple(_) => "(..)",
47 ast::StructKind::Unit => "",
50 let enum_name = parent_enum.name()?;
51 let enum_lowercase_name = to_lower_snake_case(&enum_name.to_string()).replace('_', " ");
52 let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
54 // Return early if we've found an existing new fn
55 let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
57 let target = variant.syntax().text_range();
59 &GroupLabel("Generate an `is_`,`as_`, or `try_into_` for this enum variant".to_owned()),
60 AssistId("generate_enum_is_method", AssistKind::Generate),
61 "Generate an `is_` method for this enum variant",
64 let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
66 " /// Returns `true` if the {} is [`{variant}`].
68 /// [`{variant}`]: {}::{variant}
70 {}fn {}(&self) -> bool {{
71 matches!(self, Self::{variant}{})
78 variant = variant_name
81 add_method_to_adt(builder, &parent_enum, impl_def, &method);
88 use crate::tests::{check_assist, check_assist_not_applicable};
93 fn test_generate_enum_is_from_variant() {
95 generate_enum_is_method,
109 /// Returns `true` if the variant is [`Minor`].
111 /// [`Minor`]: Variant::Minor
113 fn is_minor(&self) -> bool {
114 matches!(self, Self::Minor)
121 fn test_generate_enum_is_already_implemented() {
122 check_assist_not_applicable(
123 generate_enum_is_method,
132 fn is_minor(&self) -> bool {
133 matches!(self, Self::Minor)
140 fn test_generate_enum_is_from_tuple_variant() {
142 generate_enum_is_method,
156 /// Returns `true` if the variant is [`Minor`].
158 /// [`Minor`]: Variant::Minor
160 fn is_minor(&self) -> bool {
161 matches!(self, Self::Minor(..))
168 fn test_generate_enum_is_from_record_variant() {
170 generate_enum_is_method,
174 Minor { foo: i32 }$0,
184 /// Returns `true` if the variant is [`Minor`].
186 /// [`Minor`]: Variant::Minor
188 fn is_minor(&self) -> bool {
189 matches!(self, Self::Minor { .. })
196 fn test_generate_enum_is_from_variant_with_one_variant() {
198 generate_enum_is_method,
199 r#"enum Variant { Undefi$0ned }"#,
201 enum Variant { Undefined }
204 /// Returns `true` if the variant is [`Undefined`].
206 /// [`Undefined`]: Variant::Undefined
208 fn is_undefined(&self) -> bool {
209 matches!(self, Self::Undefined)
216 fn test_generate_enum_is_from_variant_with_visibility_marker() {
218 generate_enum_is_method,
220 pub(crate) enum Variant {
225 r#"pub(crate) enum Variant {
232 /// Returns `true` if the variant is [`Minor`].
234 /// [`Minor`]: Variant::Minor
236 pub(crate) fn is_minor(&self) -> bool {
237 matches!(self, Self::Minor)
244 fn test_multiple_generate_enum_is_from_variant() {
246 generate_enum_is_method,
255 /// Returns `true` if the variant is [`Minor`].
257 /// [`Minor`]: Variant::Minor
259 fn is_minor(&self) -> bool {
260 matches!(self, Self::Minor)
270 /// Returns `true` if the variant is [`Minor`].
272 /// [`Minor`]: Variant::Minor
274 fn is_minor(&self) -> bool {
275 matches!(self, Self::Minor)
278 /// Returns `true` if the variant is [`Major`].
280 /// [`Major`]: Variant::Major
282 fn is_major(&self) -> bool {
283 matches!(self, Self::Major)
290 fn test_generate_enum_is_variant_names() {
292 generate_enum_is_method,
294 enum GeneratorState {
299 r#"enum GeneratorState {
305 impl GeneratorState {
306 /// Returns `true` if the generator state is [`Complete`].
308 /// [`Complete`]: GeneratorState::Complete
310 fn is_complete(&self) -> bool {
311 matches!(self, Self::Complete)