diff options
Diffstat (limited to 'crates/assists/src/handlers')
-rw-r--r-- | crates/assists/src/handlers/generate_default_from_enum_variant.rs | 175 | ||||
-rw-r--r-- | crates/assists/src/handlers/invert_if.rs | 9 |
2 files changed, 184 insertions, 0 deletions
diff --git a/crates/assists/src/handlers/generate_default_from_enum_variant.rs b/crates/assists/src/handlers/generate_default_from_enum_variant.rs new file mode 100644 index 000000000..bcea46735 --- /dev/null +++ b/crates/assists/src/handlers/generate_default_from_enum_variant.rs | |||
@@ -0,0 +1,175 @@ | |||
1 | use ide_db::helpers::FamousDefs; | ||
2 | use ide_db::RootDatabase; | ||
3 | use syntax::ast::{self, AstNode, NameOwner}; | ||
4 | use test_utils::mark; | ||
5 | |||
6 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
7 | |||
8 | // Assist: generate_default_from_enum_variant | ||
9 | // | ||
10 | // Adds a Default impl for an enum using a variant. | ||
11 | // | ||
12 | // ``` | ||
13 | // enum Version { | ||
14 | // Undefined, | ||
15 | // Minor<|>, | ||
16 | // Major, | ||
17 | // } | ||
18 | // ``` | ||
19 | // -> | ||
20 | // ``` | ||
21 | // enum Version { | ||
22 | // Undefined, | ||
23 | // Minor, | ||
24 | // Major, | ||
25 | // } | ||
26 | // | ||
27 | // impl Default for Version { | ||
28 | // fn default() -> Self { | ||
29 | // Self::Minor | ||
30 | // } | ||
31 | // } | ||
32 | // ``` | ||
33 | pub(crate) fn generate_default_from_enum_variant( | ||
34 | acc: &mut Assists, | ||
35 | ctx: &AssistContext, | ||
36 | ) -> Option<()> { | ||
37 | let variant = ctx.find_node_at_offset::<ast::Variant>()?; | ||
38 | let variant_name = variant.name()?; | ||
39 | let enum_name = variant.parent_enum().name()?; | ||
40 | if !matches!(variant.kind(), ast::StructKind::Unit) { | ||
41 | mark::hit!(test_gen_default_on_non_unit_variant_not_implemented); | ||
42 | return None; | ||
43 | } | ||
44 | |||
45 | if existing_default_impl(&ctx.sema, &variant).is_some() { | ||
46 | mark::hit!(test_gen_default_impl_already_exists); | ||
47 | return None; | ||
48 | } | ||
49 | |||
50 | let target = variant.syntax().text_range(); | ||
51 | acc.add( | ||
52 | AssistId("generate_default_from_enum_variant", AssistKind::Generate), | ||
53 | "Generate `Default` impl from this enum variant", | ||
54 | target, | ||
55 | |edit| { | ||
56 | let start_offset = variant.parent_enum().syntax().text_range().end(); | ||
57 | let buf = format!( | ||
58 | r#" | ||
59 | |||
60 | impl Default for {0} {{ | ||
61 | fn default() -> Self {{ | ||
62 | Self::{1} | ||
63 | }} | ||
64 | }}"#, | ||
65 | enum_name, variant_name | ||
66 | ); | ||
67 | edit.insert(start_offset, buf); | ||
68 | }, | ||
69 | ) | ||
70 | } | ||
71 | |||
72 | fn existing_default_impl( | ||
73 | sema: &'_ hir::Semantics<'_, RootDatabase>, | ||
74 | variant: &ast::Variant, | ||
75 | ) -> Option<()> { | ||
76 | let variant = sema.to_def(variant)?; | ||
77 | let enum_ = variant.parent_enum(sema.db); | ||
78 | let krate = enum_.module(sema.db).krate(); | ||
79 | |||
80 | let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?; | ||
81 | let enum_type = enum_.ty(sema.db); | ||
82 | |||
83 | if enum_type.impls_trait(sema.db, default_trait, &[]) { | ||
84 | Some(()) | ||
85 | } else { | ||
86 | None | ||
87 | } | ||
88 | } | ||
89 | |||
90 | #[cfg(test)] | ||
91 | mod tests { | ||
92 | use test_utils::mark; | ||
93 | |||
94 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
95 | |||
96 | use super::*; | ||
97 | |||
98 | fn check_not_applicable(ra_fixture: &str) { | ||
99 | let fixture = | ||
100 | format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); | ||
101 | check_assist_not_applicable(generate_default_from_enum_variant, &fixture) | ||
102 | } | ||
103 | |||
104 | #[test] | ||
105 | fn test_generate_default_from_variant() { | ||
106 | check_assist( | ||
107 | generate_default_from_enum_variant, | ||
108 | r#" | ||
109 | enum Variant { | ||
110 | Undefined, | ||
111 | Minor<|>, | ||
112 | Major, | ||
113 | }"#, | ||
114 | r#"enum Variant { | ||
115 | Undefined, | ||
116 | Minor, | ||
117 | Major, | ||
118 | } | ||
119 | |||
120 | impl Default for Variant { | ||
121 | fn default() -> Self { | ||
122 | Self::Minor | ||
123 | } | ||
124 | }"#, | ||
125 | ); | ||
126 | } | ||
127 | |||
128 | #[test] | ||
129 | fn test_generate_default_already_implemented() { | ||
130 | mark::check!(test_gen_default_impl_already_exists); | ||
131 | check_not_applicable( | ||
132 | r#" | ||
133 | enum Variant { | ||
134 | Undefined, | ||
135 | Minor<|>, | ||
136 | Major, | ||
137 | } | ||
138 | |||
139 | impl Default for Variant { | ||
140 | fn default() -> Self { | ||
141 | Self::Minor | ||
142 | } | ||
143 | }"#, | ||
144 | ); | ||
145 | } | ||
146 | |||
147 | #[test] | ||
148 | fn test_add_from_impl_no_element() { | ||
149 | mark::check!(test_gen_default_on_non_unit_variant_not_implemented); | ||
150 | check_not_applicable( | ||
151 | r#" | ||
152 | enum Variant { | ||
153 | Undefined, | ||
154 | Minor(u32)<|>, | ||
155 | Major, | ||
156 | }"#, | ||
157 | ); | ||
158 | } | ||
159 | |||
160 | #[test] | ||
161 | fn test_generate_default_from_variant_with_one_variant() { | ||
162 | check_assist( | ||
163 | generate_default_from_enum_variant, | ||
164 | r#"enum Variant { Undefi<|>ned }"#, | ||
165 | r#" | ||
166 | enum Variant { Undefined } | ||
167 | |||
168 | impl Default for Variant { | ||
169 | fn default() -> Self { | ||
170 | Self::Undefined | ||
171 | } | ||
172 | }"#, | ||
173 | ); | ||
174 | } | ||
175 | } | ||
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs index ea722b91b..91e2f5c8c 100644 --- a/crates/assists/src/handlers/invert_if.rs +++ b/crates/assists/src/handlers/invert_if.rs | |||
@@ -69,6 +69,15 @@ mod tests { | |||
69 | use crate::tests::{check_assist, check_assist_not_applicable}; | 69 | use crate::tests::{check_assist, check_assist_not_applicable}; |
70 | 70 | ||
71 | #[test] | 71 | #[test] |
72 | fn invert_if_composite_condition() { | ||
73 | check_assist( | ||
74 | invert_if, | ||
75 | "fn f() { i<|>f x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }", | ||
76 | "fn f() { if !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }", | ||
77 | ) | ||
78 | } | ||
79 | |||
80 | #[test] | ||
72 | fn invert_if_remove_inequality() { | 81 | fn invert_if_remove_inequality() { |
73 | check_assist( | 82 | check_assist( |
74 | invert_if, | 83 | invert_if, |