1 use ide_db::helpers::FamousDefs;
2 use ide_db::RootDatabase;
3 use syntax::ast::{self, AstNode, NameOwner};
5 use crate::{AssistContext, AssistId, AssistKind, Assists};
7 // Assist: generate_default_from_enum_variant
9 // Adds a Default impl for an enum using a variant.
26 // impl Default for Version {
27 // fn default() -> Self {
32 pub(crate) fn generate_default_from_enum_variant(
36 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
37 let variant_name = variant.name()?;
38 let enum_name = variant.parent_enum().name()?;
39 if !matches!(variant.kind(), ast::StructKind::Unit) {
40 cov_mark::hit!(test_gen_default_on_non_unit_variant_not_implemented);
44 if existing_default_impl(&ctx.sema, &variant).is_some() {
45 cov_mark::hit!(test_gen_default_impl_already_exists);
49 let target = variant.syntax().text_range();
51 AssistId("generate_default_from_enum_variant", AssistKind::Generate),
52 "Generate `Default` impl from this enum variant",
55 let start_offset = variant.parent_enum().syntax().text_range().end();
59 impl Default for {0} {{
60 fn default() -> Self {{
64 enum_name, variant_name
66 edit.insert(start_offset, buf);
71 fn existing_default_impl(
72 sema: &'_ hir::Semantics<'_, RootDatabase>,
73 variant: &ast::Variant,
75 let variant = sema.to_def(variant)?;
76 let enum_ = variant.parent_enum(sema.db);
77 let krate = enum_.module(sema.db).krate();
79 let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?;
80 let enum_type = enum_.ty(sema.db);
82 if enum_type.impls_trait(sema.db, default_trait, &[]) {
91 use crate::tests::{check_assist, check_assist_not_applicable};
95 fn check_not_applicable(ra_fixture: &str) {
97 format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE);
98 check_assist_not_applicable(generate_default_from_enum_variant, &fixture)
102 fn test_generate_default_from_variant() {
104 generate_default_from_enum_variant,
117 impl Default for Variant {
118 fn default() -> Self {
126 fn test_generate_default_already_implemented() {
127 cov_mark::check!(test_gen_default_impl_already_exists);
128 check_not_applicable(
136 impl Default for Variant {
137 fn default() -> Self {
145 fn test_add_from_impl_no_element() {
146 cov_mark::check!(test_gen_default_on_non_unit_variant_not_implemented);
147 check_not_applicable(
158 fn test_generate_default_from_variant_with_one_variant() {
160 generate_default_from_enum_variant,
161 r#"enum Variant { Undefi$0ned }"#,
163 enum Variant { Undefined }
165 impl Default for Variant {
166 fn default() -> Self {