1 use ide_db::{famous_defs::FamousDefs, RootDatabase};
2 use syntax::ast::{self, AstNode, HasName};
4 use crate::{AssistContext, AssistId, AssistKind, Assists};
6 // Assist: generate_default_from_enum_variant
8 // Adds a Default impl for an enum using a variant.
25 // impl Default for Version {
26 // fn default() -> Self {
31 pub(crate) fn generate_default_from_enum_variant(
33 ctx: &AssistContext<'_>,
35 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
36 let variant_name = variant.name()?;
37 let enum_name = variant.parent_enum().name()?;
38 if !matches!(variant.kind(), ast::StructKind::Unit) {
39 cov_mark::hit!(test_gen_default_on_non_unit_variant_not_implemented);
43 if existing_default_impl(&ctx.sema, &variant).is_some() {
44 cov_mark::hit!(test_gen_default_impl_already_exists);
48 let target = variant.syntax().text_range();
50 AssistId("generate_default_from_enum_variant", AssistKind::Generate),
51 "Generate `Default` impl from this enum variant",
54 let start_offset = variant.parent_enum().syntax().text_range().end();
58 impl Default for {enum_name} {{
59 fn default() -> Self {{
64 edit.insert(start_offset, buf);
69 fn existing_default_impl(
70 sema: &'_ hir::Semantics<'_, RootDatabase>,
71 variant: &ast::Variant,
73 let variant = sema.to_def(variant)?;
74 let enum_ = variant.parent_enum(sema.db);
75 let krate = enum_.module(sema.db).krate();
77 let default_trait = FamousDefs(sema, krate).core_default_Default()?;
78 let enum_type = enum_.ty(sema.db);
80 if enum_type.impls_trait(sema.db, default_trait, &[]) {
89 use crate::tests::{check_assist, check_assist_not_applicable};
94 fn test_generate_default_from_variant() {
96 generate_default_from_enum_variant,
112 impl Default for Variant {
113 fn default() -> Self {
122 fn test_generate_default_already_implemented() {
123 cov_mark::check!(test_gen_default_impl_already_exists);
124 check_assist_not_applicable(
125 generate_default_from_enum_variant,
127 //- minicore: default
134 impl Default for Variant {
135 fn default() -> Self {
144 fn test_add_from_impl_no_element() {
145 cov_mark::check!(test_gen_default_on_non_unit_variant_not_implemented);
146 check_assist_not_applicable(
147 generate_default_from_enum_variant,
149 //- minicore: default
160 fn test_generate_default_from_variant_with_one_variant() {
162 generate_default_from_enum_variant,
164 //- minicore: default
165 enum Variant { Undefi$0ned }
168 enum Variant { Undefined }
170 impl Default for Variant {
171 fn default() -> Self {